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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

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

  1. Неявное преобразование типов (ошибка с литералом даты). Использование текстовой строки вида "20190421" вместо полноценного типа данных Дата заставляет платформу принудительно выполнять приведение типов. Если такое преобразование завершается неудачей на уровне СУБД, запись может не создаться или создаться с пустой датой, из-за чего она "улетает" в самое начало списка.
  2. Активные фильтры в форме списка. Часто запись успешно физически попадает в базу данных, но пользователь не видит ее на форме списка из-за наложенных отборов. Для надежной проверки всегда используйте консоль запросов.
  3. Проблемы обновления интерфейса. Динамический список на управляемой форме не всегда мгновенно реагирует на фоновые или программные изменения в базе данных. Попробуйте обновить форму вручную (кнопка "Еще" — "Обновить" или клавиша F5).

Теперь рассмотрим два основных подхода к программной записи в регистры сведений: использование набора записей и использование менеджера записи.

Способ №1. Использование Набора записей (РегистрСведенийНаборЗаписей)

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

Рассмотрим правильный и безопасный шаблон кода для работы с набором записей:


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

// Находим необходимую валюту в справочнике
Доллар = Справочники.Валюты.НайтиПоНаименованию("Доллар");

// Устанавливаем жесткий отбор по ключевым измерениям. 
// Это критически важно, чтобы не затереть лишние данные в базе!
НаборЗаписей.Отбор.Валюта.Установить(Доллар); 
НаборЗаписей.Отбор.Период.Установить('20190421'); 

// Читаем существующие записи из базы по установленным отборам
НаборЗаписей.Прочитать();

// Проверяем, есть ли уже такая запись в базе данных
Если НаборЗаписей.Количество() = 0 Тогда
    // Если записи нет — добавляем новую строку в коллекцию
    НовЗапись = НаборЗаписей.Добавить(); 
    НовЗапись.Период = '20190421'; 
    НовЗапись.Валюта = Доллар; 
Иначе
    // Если запись существует — берем ее для редактирования
    НовЗапись = НаборЗаписей[0];
КонецЕсли;

// Заполняем ресурсы и реквизиты записи
НовЗапись.Курс = 57; 
НовЗапись.Кратность = 1; 

// Записываем набор в базу данных с включенным замещением
НаборЗаписей.Записать(Истина);

Внимание! Смертельная опасность параметра "Замещать"!
В методе НаборЗаписей.Записать(Истина) параметр Истина указывает платформе на необходимость замещения. Система находит в базе абсолютно все записи, соответствующие установленным в объекте Отбор значениям, удаляет их и вставляет новые записи из текущего набора.
Запомните правило: если вы забудете установить отборы в наборе записей и вызовете Записать(Истина) для пустого набора, система бесследно удалит абсолютно все записи из этого регистра сведений!

Способ №2. Использование Менеджера записи (РегистрСведенийМенеджерЗаписи)

Если перед вами стоит задача создать, прочитать или обновить всего одну конкретную строку в независимом регистре сведений, использование набора записей является избыточным. Для этих целей гораздо проще и безопаснее применять специальный объект — РегистрСведенийМенеджерЗаписи.

Менеджер записи работает по принципу объектной модели (подобно документу или элементу справочника). Рассмотрим, как выглядит аналогичная процедура записи с его помощью:


// Создаем объект менеджера записи для независимого регистра
МенеджерЗаписи = РегистрыСведений.КурсВалют.СоздатьМенеджерЗаписи();

Доллар = Справочники.Валюты.НайтиПоНаименованию("Доллар");

// Заполняем ключевые поля (измерения и период), по которым будет выполняться поиск
МенеджерЗаписи.Период = '20190421';
МенеджерЗаписи.Валюта = Доллар;

// Пытаемся прочитать существующую запись из базы данных
МенеджерЗаписи.Прочитать();

// Независимо от того, была ли найдена запись, заполняем/обновляем ресурсы
МенеджерЗаписи.Курс = 57;
МенеджерЗаписи.Кратность = 1;

// Физически записываем изменения в базу данных. 
// Платформа сама поймет, нужно ли сделать INSERT или UPDATE.
МенеджерЗаписи.Записать(Истина);

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

Важные правила работы с литералами дат

Выясним причину споров разработчиков на форуме касательно формата даты. В коде автора из примера фигурирует конструкция "20190421". Это обычная текстовая строка. Написание даты в таком формате является грубой архитектурной ошибкой.

Для корректной работы платформы и СУБД используйте только явные способы представления даты:

Режим записи регистра: Независимый vs Подчиненный регистратору

Перед написанием кода обязательно проверьте свойства вашего регистра в конфигураторе:


НаборЗаписей = РегистрыСведений.РегистрПодчиненный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);

НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Регистратор = СсылкаНаДокумент;
// Заполнение остальных полей...

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

Современные стандарты разработки 1С и оптимизация СУБД

Если вы работаете в высоконагруженных системах или используете платформу версии 8.3.26 и выше, обратите внимание на новые стандарты производительности при записи регистров:

  1. Новые режимы замещения (платформа 8.3.26 и 8.3.27): В современных версиях платформы появились специализированные режимы пакетного изменения данных. Вместо полной перезаписи наборов данных (которая сильно нагружает журналы транзакций СУБД) используйте новые режимы: в 8.3.26 появился режим замещения Удаление, а в 8.3.27 — режимы Обновление и Слияние. Это позволяет точечно вносить изменения на уровне базы данных.
  2. Ограничение на перезапись больших наборов данных: Согласно техническим стандартам фирмы "1С", если в записываемом наборе изменяется менее 30% строк, не рекомендуется перезаписывать весь набор целиком. Это приводит к избыточной нагрузке и блокировкам таблиц. Обновляйте только точечно измененные данные.
  3. Запись порциями при больших объемах: Никогда не записывайте огромные массивы данных в цикле по одной записи. Это критически замедляет работу системы. При массовом импорте или переносе данных группируйте записи в наборы порциями примерно по 1000 строк.
  4. Управляемые блокировки данных: При многопользовательской работе запись набора данных без предварительной блокировки может привести к взаимным блокировкам (Deadlocks) транзакций СУБД. Перед вызовом методов чтения и записи устанавливайте управляемую блокировку:

Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.КурсВалют");
ЭлементБлокировки.УстановитьЗначение("Валюта", Доллар);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

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

← На главную