Разработка и Конфигурация · 11 мин
Как сделать запись в регистр сведений программно в 1С
Как программно записать данные в регистр сведений 1С: менеджер записи, набор записей, добавление и изменение записей, типичные ошибки и примеры кода.
Регистр сведений в 1С предназначен для хранения информации в разрезе заданных измерений: курсов валют, цен номенклатуры, настроек, адресов контрагентов. Программная запись в регистр сведений — одна из базовых операций при разработке и доработке конфигураций, и выполняется она двумя основными способами: через менеджер записи (для одной записи) и через набор записей (для одной или нескольких записей сразу).
Выбор способа зависит от задачи. Если нужно добавить или изменить одну запись по конкретному ключу измерений — удобнее менеджер записи. Если требуется записать пакет данных, полностью заменить записи по отбору или удалить группу записей — используется набор записей. Ошибка в выборе механизма приводит либо к неэффективному коду (множество отдельных обращений к базе вместо одной транзакции), либо к непреднамеренному удалению данных.
Ниже разобраны оба способа с примерами кода, особенности работы с периодическими и подчинёнными регистраторами регистрами, проверка результата и типичные ошибки, которые допускают разработчики при записи в регистры сведений.
Что нужно знать о регистре сведений перед записью
Перед написанием кода важно понять структуру конкретного регистра. Откройте его в конфигураторе и проверьте: какие измерения определены, какие ресурсы и реквизиты существуют, является ли регистр периодическим и подчинён ли он регистратору. От этого зависит, какие поля обязательны для заполнения и каким способом вообще возможна запись.
Независимый регистр сведений позволяет писать в него напрямую из кода. Регистр, подчинённый регистратору, изменяется только через движения документа — попытка записать его программно без указания регистратора приведёт к ошибке. Периодический регистр дополнительно требует заполнения поля Период, которое участвует в ключе уникальности записи вместе с измерениями.
Уникальность записи определяется комбинацией измерений (и периода для периодического регистра). Если запись с таким ключом уже существует, метод Записать() не создаст дубликат, а перезапишет существующую строку. Это удобно для обновления данных, но опасно, если вы не рассчитывали на затирание прежних значений.
Запись одной строки через менеджер записи
Менеджер записи — объект, представляющий одну строку регистра. Он подходит, когда нужно добавить или обновить одну запись по известному ключу измерений. Код получается коротким и читаемым.
МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ТекущаяДатаСеанса();
МенеджерЗаписи.Валюта = ВалютаСсылка;
МенеджерЗаписи.Курс = 90.5;
МенеджерЗаписи.Кратность = 1;
МенеджерЗаписи.Записать();
Метод Записать() без параметра работает в режиме замещения: если запись с таким ключом существует, она будет обновлена. Если записи нет — будет создана новая. Перед записью можно проверить существование записи, вызвав МенеджерЗаписи.Прочитать() после заполнения ключевых полей: если запись найдена, свойство МенеджерЗаписи.Выбран() вернёт Истина.
Для удаления одной записи используется тот же менеджер: заполните измерения (и период), затем вызовите МенеджерЗаписи.Удалить(). Это безопаснее, чем удаление через набор записей, когда речь идёт об одной конкретной строке.
Пакетная запись через набор записей
Набор записей — коллекция строк регистра с возможностью установки отбора. Он незаменим, когда нужно записать несколько строк одной транзакцией или полностью заменить данные по определённому отбору. Типичный сценарий — загрузка курсов валют за месяц или обновление цен по списку номенклатуры.
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ТипЦен.Установить(ТипЦенСсылка);
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Номенклатура = СтрокаТовара.Номенклатура;
НоваяЗапись.ТипЦен = ТипЦенСсылка;
НоваяЗапись.Цена = СтрокаТовара.Цена;
КонецЦикла;
НаборЗаписей.Записать(Истина);
Параметр Истина в методе Записать() означает замещение: все существующие записи, попадающие под отбор, будут удалены и заменены содержимым набора. Если вызвать Записать(Ложь), записи набора будут добавлены к существующим, но при совпадении ключей возникнет ошибка уникальности.
Критически важный момент: если вы установили отбор и вызвали Записать(Истина) на пустом наборе, все записи по этому отбору будут удалены. Это штатный способ очистки данных по отбору, но при ошибке в отборе можно удалить лишнее. Всегда проверяйте, что отбор установлен корректно и до записи.
Особенности периодических регистров и регистров с регистратором
В периодическом регистре сведений поле Период входит в ключ записи. Это значит, что по одной и той же комбинации измерений может существовать множество записей с разными датами. При записи через менеджер записи обязательно заполняйте период, иначе запись ляжет на пустую дату, что обычно является ошибкой.
Для чтения актуальных значений периодического регистра используйте методы ПолучитьПоследнее() и ПолучитьПервое() менеджера регистра, а также виртуальные таблицы СрезПоследних и СрезПервых в запросах. Прямая запись в периодический регистр не трогает эти механизмы — они работают на уровне запросов.
Если регистр подчинён регистратору, программная запись возможна только через набор записей, отобранный по регистратору, обычно внутри обработки проведения документа:
Движения.СтатусыЗаказов.Записывать = Истина;
Движение = Движения.СтатусыЗаказов.Добавить();
Движение.Период = Дата;
Движение.Заказ = ЗаказСсылка;
Движение.Статус = Перечисления.Статусы.ВРаботе;
Транзакции и производительность при массовой записи
При загрузке больших объёмов данных (тысячи и десятки тысяч записей) не записывайте каждую строку отдельным менеджером записи — это порождает отдельное обращение к базе на каждую итерацию и работает на порядки медленнее. Собирайте данные в набор записей и записывайте пакетами, например по 1000–5000 строк.
Для операций, которые должны выполниться целиком или не выполниться вовсе, используйте явные транзакции: НачатьТранзакцию(), ЗафиксироватьТранзакцию(), ОтменитьТранзакцию(). Это защищает от ситуации, когда часть данных записалась, а часть — нет из-за ошибки в середине цикла.
На больших регистрах учитывайте блокировки. Запись с замещением по широкому отбору может заблокировать значительную часть таблицы регистра и вызвать конфликты с работой пользователей. Массовые загрузки лучше выполнять вне пиковой нагрузки или порциями в фоновом задании.
- 1Определите структуру регистра: измерения, периодичность, подчинение регистратору
- 2Создайте менеджер записи через РегистрыСведений.ИмяРегистра.СоздатьМенеджерЗаписи()
- 3Заполните все измерения и период (для периодического регистра)
- 4Заполните ресурсы и нужные реквизиты
- 5Вызовите Записать() и перехватите возможное исключение
- 6Проверьте результат запросом или через форму списка регистра
Проверка результата записи
После выполнения кода убедитесь, что данные действительно записались так, как задумано. Самый простой способ — открыть форму списка регистра в режиме предприятия и отфильтровать по известному ключу. Для программной проверки используйте запрос или чтение через менеджер записи.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КурсыВалют.Период,
| КурсыВалют.Курс
|ИЗ
| РегистрСведений.КурсыВалют КАК КурсыВалют
|ГДЕ
| КурсыВалют.Валюта = &Валюта";
Запрос.УстановитьПараметр("Валюта", ВалютаСсылка);
Результат = Запрос.Выполнить().Выгрузить();
Признаки успешной записи: запрос возвращает строки с ожидаемыми значениями, количество записей соответствует загруженному, старые данные по отбору либо обновлены, либо замещены (в зависимости от режима). Если записей нет — проверьте, не завернулся ли код в исключение, которое было «проглочено» пустым обработчиком Попытка...Исключение.
Как проверить результат
Совпадает с числом загружаемых строк
Меньше ожидаемого или ноль — часть данных не записалась
Соответствуют источнику данных
Пустые или старые значения — запись не выполнилась или перезаписана
Не изменились
Пропали чужие записи — отбор был установлен неверно
Типичные ошибки и способы их избежать
Самая разрушительная ошибка — вызов Записать(Истина) на наборе без отбора, что приводит к полной очистке регистра. Вторая по частоте — запись без заполнения обязательных измерений: система либо выдаст ошибку, либо создаст запись с пустым ключом, которая потом будет мешать в выборках.
Также часто встречаются: запись в подчинённый регистратору регистр без указания регистратора (ошибка выполнения), игнорирование периода в периодическом регистре, использование менеджера записи в цикле для массовой загрузки (катастрофическое падение производительности) и отсутствие транзакции при пакетной записи.
Ещё одна группа проблем — права доступа. Код, выполняемый в контексте пользователя, может молча не записать данные, если у пользователя нет прав на изменение регистра. В серверных процедурах, где это осознанное решение, используйте УстановитьПривилегированныйРежим(Истина), но только там, где это действительно необходимо.
Часто задаваемые вопросы
Чем менеджер записи отличается от набора записей?
Менеджер записи работает ровно с одной строкой регистра и удобен для точечных операций: добавить, прочитать, удалить одну запись. Набор записей — это коллекция строк с отбором, предназначенная для пакетной записи, замещения группы записей и очистки данных по отбору. Для массовых операций всегда выбирайте набор записей.
Как обновить существующую запись, а не создать новую?
Заполните в менеджере записи все измерения (и период для периодического регистра), затем вызовите Прочитать() — объект заполнится текущими значениями. Измените нужные реквизиты и вызовите Записать(). Поскольку ключ записи совпадает, существующая строка будет обновлена, а не продублирована.
Можно ли программно записать регистр сведений, подчинённый регистратору?
Напрямую — нет. Такие регистры изменяются только через движения документа: в обработке проведения заполните коллекцию Движения.ИмяРегистра и установите свойство Записывать = Истина. Альтернатива для служебных сценариев — создать набор записей с отбором по регистратору и записать его, но это должно быть согласовано с логикой проведения документа.
Как удалить все записи регистра сведений по условию?
Создайте набор записей, установите отбор по нужным измерениям и вызовите Записать(Истина), не добавляя строк в набор. Все записи, попадающие под отбор, будут удалены. Перед выполнением на рабочей базе обязательно проверьте отбор и сделайте резервную копию — операция необратима.
Почему код выполняется без ошибок, но записи в регистре не появляются?
Чаще всего причины такие: исключение перехвачено пустым блоком Попытка/Исключение; у пользователя нет прав на изменение регистра; транзакция была отменена выше по стеку вызовов; запись выполняется, но сразу затирается другим кодом или обменом данными. Проверяйте журнал регистрации и добавляйте осмысленную обработку исключений с выводом текста ошибки.
Как безопасно загрузить в регистр десятки тысяч записей?
Используйте набор записей с записью порциями (например, по несколько тысяч строк), оберните каждую порцию в транзакцию, выполняйте загрузку в фоновом задании вне часов пиковой нагрузки и предварительно протестируйте код на копии базы. Не пишите каждую строку отдельным менеджером записи — это критично для производительности.
Что важно запомнить
Одна запись — менеджер записи, пакет или замещение по отбору — набор записей. Всегда заполняйте все измерения и период, никогда не вызывайте Записать(Истина) без отбора, массовые загрузки выполняйте порциями в транзакциях, а результат проверяйте запросом или формой списка.