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

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

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

Анализ частых ошибок при обновлении регистра сведений

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

  1. Обращение к полям напрямую через РегистрСведенийНаборЗаписей. Объект НаборЗаписей представляет собой коллекцию строк (записей), а не отдельную запись. Попытка написать НаборЗаписей.Ресурс = Значение приводит к ошибке «Поле объекта не обнаружено». Для изменения значений необходимо выполнять обход записей набора в цикле.
  2. Неполная инициализация ключевых полей в РегистрСведенийМенеджерЗаписи. Менеджер записи предназначен для работы строго с одной записью. Чтобы метод Прочитать() нашел существующую запись, необходимо заполнить все ключевые поля (все измерения регистра, а для периодических регистров — поле Период, для подчиненных регистратору — поле Регистратор). Если хотя бы одно ключевое поле не указано, платформа считает запись новой, что приводит к созданию дубликата или ошибке «Период не может быть пустым».

Способ 1. Обновление записей с использованием объекта НаборЗаписей

Проанализируем классический и наиболее гибкий способ модификации записей с помощью РегистрСведенийНаборЗаписей. Этот подход работает как с независимыми регистрами, так и с регистрами, подчиненными регистратору.

Разберем по шагам правильный алгоритм работы:

  1. Создаем набор записей через менеджер регистра сведений.
  2. Устанавливаем необходимые отборы по измерениям (или регистратору), чтобы ограничить область чтения и последующей перезаписи только нужными строками.
  3. Считываем отобранные данные из базы методом Прочитать().
  4. Обходим элементы коллекции в цикле Для Каждого ... Из ... Цикл и модифицируем необходимые ресурсы.
  5. Фиксируем изменения в базе данных с помощью метода Записать().

Посмотрим на пример программного кода:


НаборЗаписейЗанятыхЯчеек = РегистрыСведений.ЗанятыеЯчейки.СоздатьНаборЗаписей();

// Устанавливаем отборы по измерениям
НаборЗаписейЗанятыхЯчеек.Отбор.ДатаНачала.Установить(Строка.ДатаНачала);
НаборЗаписейЗанятыхЯчеек.Отбор.ДатаОкончания.Установить(Строка.ДатаОкончания);
НаборЗаписейЗанятыхЯчеек.Отбор.Ячейка.Установить(Строка.Ячейка);

// Считываем записи из базы данных
НаборЗаписейЗанятыхЯчеек.Прочитать();

// Обходим прочитанные записи и меняем ресурсы
Для Каждого Запись Из НаборЗаписейЗанятыхЯчеек Цикл
    Если Запись.СтоимостьЕдиницы = 0 Тогда
        Запись.СтоимостьЕдиницы = Сумма;
    КонецЕсли;
КонецЦикла;

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

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

Способ 2. Использование объекта МенеджерЗаписи для точечного изменения

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


МенеджерЗаписи = РегистрыСведений.ЗанятыеЯчейки.СоздатьМенеджерЗаписи();

// Заполняем ВСЕ ключевые поля (измерения и период при наличии)
МенеджерЗаписи.Период = Строка.Период;
МенеджерЗаписи.ДатаНачала = Строка.ДатаНачала;
МенеджерЗаписи.ДатаОкончания = Строка.ДатаОкончания;
МенеджерЗаписи.Ячейка = Строка.Ячейка;

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

// Проверяем, существует ли запись в информационной базе
Если МенеджерЗаписи.Выбран() Тогда
    МенеджерЗаписи.СтоимостьЕдиницы = Сумма;
    МенеджерЗаписи.Записать(Истина);
КонецЕсли;

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

Способ 3. Модификация записей через коллекцию Движения документа

Если регистр сведений подчинен регистратору, а корректировка записей выполняется в контексте документа (например, в процедуре ОбработкаПроведения модуля объекта), то правильнее всего работать напрямую с коллекцией Движения документа.

Рассмотрим пример заполнения или корректировки движений внутри модуля документа:


// Включаем флаг обязательной записи движений по регистру
Движения.ЗанятыеЯчейки.Записывать = Истина;

// Обходим уже сформированные движения документа
Для Каждого Движение Из Движения.ЗанятыеЯчейки Цикл
    Если Движение.СтоимостьЕдиницы = 0 Тогда
        Движение.СтоимостьЕдиницы = РассчитаннаяСумма;
    КонецЕсли;
КонецЦикла;

Особенности работы с движениями документа:

  1. Свойство Записывать = Истина сообщает платформе о необходимости сохранить сформированный набор движений в транзакции проведения документа.
  2. Не рекомендуется изменять движения документов из внешних обработок или событий формы (например, ПриЗакрытии) в обход проведения, так как при последующем штатном перепроведении документа эти изменения будут автоматически перезаписаны. Для актуализации данных подчиненных регистров следует вызывать полное перепроведение документа.
← На главную