К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно записать в регистр сведений в 1С

Разбираем, как программно записать данные в регистр сведений 1С: менеджер записи, набор записей, подчинение регистратору, типовые ошибки и проверка результата.

Регистр сведений в 1С хранит информацию в разрезе измерений и, при необходимости, периода: курсы валют, цены номенклатуры, штрихкоды, настройки обмена. Записывать данные в него можно вручную через форму списка, но в прикладном коде чаще требуется программная запись — при обменах, загрузке данных из файлов, обработчиках событий и фоновых заданиях.

Для программной записи в регистр сведений существуют два основных механизма: менеджер записи (одна строка регистра) и набор записей (группа строк с общим отбором). Выбор зависит от структуры регистра — независимый он или подчинён регистратору — и от того, нужно ли записать одну запись или пакет.

Ошибки при программной записи приводят к дублям, затиранию существующих данных или потере связи с документом-регистратором. Ниже разобраны оба механизма с примерами кода, отличия для периодических и подчинённых регистров, контроль результата и типичные проблемы.

Как устроен регистр сведений и что нужно знать перед записью

Перед написанием кода определите три свойства регистра в конфигураторе. Первое — режим записи: независимый или подчинённый регистратору. Независимый регистр заполняется напрямую, подчинённый — только с указанием документа-регистратора, обычно при проведении.

Второе свойство — периодичность. Периодический регистр хранит историю значений (например, цену на дату), и при записи обязательно указывается поле Период. Непериодический регистр хранит только актуальное состояние в разрезе измерений.

Третье — состав измерений. Совокупность измерений (и периода для периодического регистра) образует уникальный ключ записи. Попытка записать строку с уже существующим ключом без установки отбора приведёт либо к перезаписи, либо к ошибке уникальности — в зависимости от способа записи.

Запись одной строки через менеджер записи

Менеджер записи подходит, когда нужно добавить или изменить одну конкретную запись независимого регистра сведений. Это самый простой и наиболее часто используемый способ.

МенеджерЗаписи = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Период = ТекущаяДатаСеанса();

МенеджерЗаписи.Номенклатура = НоменклатураСсылка;

МенеджерЗаписи.ВидЦены = ВидЦеныСсылка;

МенеджерЗаписи.Цена = 1500;

МенеджерЗаписи.Записать();

Метод Записать() без параметров работает в режиме замещения: если запись с таким ключом уже существует, она будет перезаписана. Если нужно запретить замещение и получить исключение при дубликате, используйте МенеджерЗаписи.Записать(Ложь) — тогда платформа выдаст ошибку о нарушении уникальности.

Чтобы изменить существующую запись, а не создать новую, сначала заполните ключевые поля (измерения и период), вызовите Прочитать(), проверьте МенеджерЗаписи.Выбран(), затем измените ресурсы и запишите. Это защищает от случайного создания дублей при обновлении данных.

bsl
МенеджерЗаписи = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Номенклатура = НоменклатураСсылка;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
    МенеджерЗаписи.Штрихкод = НовыйШтрихкод;
    МенеджерЗаписи.Записать();
КонецЕсли;

Пакетная запись через набор записей

Набор записей используется, когда требуется записать несколько строк за одну операцию или полностью заменить группу записей с одинаковым отбором. Типичный сценарий — загрузка курсов валют за месяц или перезапись настроек по одному объекту.

НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Валюта.Установить(ВалютаСсылка);

Для Каждого СтрокаДанных Из ТаблицаКурсов Цикл

НоваяЗапись = НаборЗаписей.Добавить();

НоваяЗапись.Период = СтрокаДанных.Дата;

НоваяЗапись.Валюта = ВалютаСсылка;

НоваяЗапись.Курс = СтрокаДанных.Курс;

КонецЦикла;

НаборЗаписей.Записать();

Ключевой момент: набор записей при записи полностью замещает все строки, попадающие под установленный отбор. Если вы установили отбор по валюте и записали набор из пяти строк, все прежние записи по этой валюте будут удалены и заменены новыми. Это удобно для полного обновления, но опасно при частичном.

Если нужно только добавить строки к существующим, сначала вызовите НаборЗаписей.Прочитать(), затем добавляйте новые строки и записывайте. Либо используйте параметр Записать(Ложь), который добавляет записи без замещения — но при совпадении ключей возникнет ошибка уникальности.

Запись в регистр, подчинённый регистратору

Если регистр сведений подчинён регистратору, каждая запись обязательно содержит ссылку на документ-регистратор. Такие регистры обычно заполняются в обработчике проведения документа, а не напрямую из произвольного кода.

В модуле документа движения формируются через коллекцию Движения:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Движения.СтатусыЗаказов.Записывать = Истина;

Движение = Движения.СтатусыЗаказов.Добавить();

Движение.Период = Дата;

Движение.Заказ = ЗаказПокупателя;

Движение.Статус = Перечисления.СтатусыЗаказа.ВРаботе;

КонецПроцедуры

Платформа сама запишет движения при проведении документа и удалит их при отмене проведения. Принудительная запись набора вне проведения возможна (через создание набора записей с отбором по регистратору), но нарушает логику: при следующем перепроведении документа такие записи будут затёрты.

Транзакции и запись нескольких регистров

Когда программная обработка пишет в несколько регистров или комбинирует запись регистра сведений с изменением других объектов, оборачивайте операции в транзакцию. Иначе при ошибке на середине часть данных будет записана, а часть — нет, и база останется в несогласованном состоянии.

НачатьТранзакцию();

Попытка

// запись в первый регистр

// запись во второй регистр

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ВызватьИсключение ОписаниеОшибки();

КонецПопытки;

Учитывайте, что длительные транзакции с массовой записью увеличивают риск блокировок в многопользовательской среде. Для больших пакетов разбивайте загрузку на порции и фиксируйте транзакцию на каждой порции — так конфликты блокировок будут затрагивать меньший объём данных.

Порядок действий при программной записи
  1. 1
    Определите режим записи регистра (независимый или подчинённый регистратору) и его периодичность
  2. 2
    Выберите механизм: менеджер записи для одной строки, набор записей для пакета
  3. 3
    Заполните все измерения, период (для периодического регистра), ресурсы и реквизиты
  4. 4
    При пакетной записи установите отбор и решите, нужно ли предварительное чтение существующих данных
  5. 5
    Выполните Записать() и проверьте результат запросом или через форму списка регистра

Проверка результата и типичные ошибки

После записи убедитесь, что данные действительно в регистре. Быстрый способ — запрос через консоль запросов или открытие формы списка регистра с отбором по записанным измерениям. Признаком успеха является наличие строки с ожидаемым ключом и значениями ресурсов.

Наиболее частые проблемы: запись не появляется из-за исключения, «проглоченного» пустой обработкой ошибок; появляются дубли, потому что разные представления периода (начало дня и произвольное время) дают разные ключи; данные затирают соседние записи из-за слишком широкого отбора набора записей.

Типичные ошибки
01
Запись набора без Прочитать() — все прежние записи под отбором удаляются
02
Не заполнен Период в периодическом регистре — запись уходит на пустую дату и «теряется» в списке
03
Попытка записи в подчинённый регистр без регистратора — ошибка или потеря данных при перепроведении документа
04
Разное время в поле Период при повторной записи — вместо обновления создаётся дубль
05
Игнорирование исключений в Попытка/Исключение без логирования — ошибки записи остаются незамеченными
Контрольные точки

Как проверить результат

Наличие записи
Норма

Запрос по ключу возвращает строку с ожидаемыми ресурсами

Тревожный признак

Запрос пуст — запись не выполнена или ключ отличается

Количество записей под отбором
Норма

Число строк соответствует ожиданию после пакетной записи

Тревожный признак

Строк меньше — часть затёрта; больше — появились дубли

Период записи
Норма

Дата соответствует переданному значению

Тревожный признак

Пустая дата или неожиданное время — поле Период не заполнено корректно

Выбор между менеджером записи и набором записей

Менеджер записи проще и безопаснее для точечных операций: он не может случайно затереть чужие данные, потому что работает строго с одной строкой. Набор записей эффективнее при массовой загрузке — одна операция записи вместо сотен отдельных вызовов существенно быстрее.

Для подчинённых регистров выбора фактически нет: используется набор записей через механизм движений документа. Для независимых регистров ориентируйтесь на объём: до нескольких десятков записей разница незаметна, при тысячах строк выигрывает набор записей.

Сравнение способов записи

Менеджер записи

Одна запись за вызов, простой код, нет риска затереть соседние строки. Медленно при массовой загрузке.

Набор записей с отбором

Быстрая пакетная запись, полное замещение данных под отбором. Требует аккуратности с отбором и чтением.

Движения документа

Единственный корректный способ для регистров, подчинённых регистратору. Запись привязана к проведению документа.

Итог

Что важно запомнить

Одну запись в независимый регистр пишите менеджером записи, пакет — набором записей с аккуратно установленным отбором, подчинённый регистратору регистр — через движения документа. Всегда заполняйте измерения и период, проверяйте результат запросом, а массовые операции выполняйте в транзакции.

Часто задаваемые вопросы

Чем отличается Записать(Истина) от Записать(Ложь) у набора записей?

Параметр Истина (значение по умолчанию) означает замещение: все существующие записи, попадающие под отбор, удаляются и заменяются содержимым набора. Параметр Ложь означает добавление: новые строки дописываются к существующим, но при совпадении ключа записи возникнет ошибка уникальности.

Как удалить запись из регистра сведений программно?

Для одной записи создайте менеджер записи, заполните измерения и период, затем вызовите Удалить(). Для группы записей создайте набор записей с нужным отбором и вызовите Записать() у пустого набора — все строки под отбором будут удалены. Действуйте осторожно: операция необратима.

Почему запись не появляется в регистре, хотя ошибок нет?

Частые причины: запись выполняется в транзакции, которая затем отменяется; исключение перехватывается пустым блоком Исключение; запись уходит с другим ключом (например, с другим временем в поле Период), поэтому при просмотре с отбором её не видно. Проверьте регистрацию ошибок и выполните запрос без отборов.

Можно ли записать в подчинённый регистр сведений без проведения документа?

Технически да: создайте набор записей, установите отбор по регистратору, заполните строки и запишите. Однако при следующем перепроведении документа платформа перезапишет движения, и ваши изменения пропадут. Корректный путь — формировать записи в обработчике проведения.

Как обновить существующую запись, не создавая дубль?

Заполните в менеджере записи все измерения и период точно так же, как у существующей записи, вызовите Прочитать(), измените ресурсы и запишите. Если ключ совпадает, запись обновится. Если хотя бы одно измерение отличается — будет создана новая строка.

Что быстрее при загрузке тысяч записей: менеджер записи или набор?

Набор записей значительно быстрее, потому что вся пачка строк пишется одной операцией обращения к базе данных. Менеджер записи выполняет отдельную операцию на каждую строку. При больших объёмах также помогает разбивка на порции с фиксацией транзакции на каждой порции.