При разработке конфигураций на платформе 1С:Предприятие часто возникает задача точечного обновления или заполнения пустых ресурсов в существующих записях регистра сведений. Начинающие разработчики нередко сталкиваются с ошибками при попытке обращаться к ресурсам регистра напрямую через объект набора записей или получают дубликаты записей и системные ошибки при использовании менеджера записи. Разберем подробно, почему возникают эти ошибки и какими способами можно корректно обновить данные.
Рассмотрим две наиболее распространенные ошибки при попытке изменить запись в регистре сведений:
РегистрСведенийНаборЗаписей. Объект НаборЗаписей представляет собой коллекцию строк (записей), а не отдельную запись. Попытка написать НаборЗаписей.Ресурс = Значение приводит к ошибке «Поле объекта не обнаружено». Для изменения значений необходимо выполнять обход записей набора в цикле.РегистрСведенийМенеджерЗаписи. Менеджер записи предназначен для работы строго с одной записью. Чтобы метод Прочитать() нашел существующую запись, необходимо заполнить все ключевые поля (все измерения регистра, а для периодических регистров — поле Период, для подчиненных регистратору — поле Регистратор). Если хотя бы одно ключевое поле не указано, платформа считает запись новой, что приводит к созданию дубликата или ошибке «Период не может быть пустым».Проанализируем классический и наиболее гибкий способ модификации записей с помощью РегистрСведенийНаборЗаписей. Этот подход работает как с независимыми регистрами, так и с регистрами, подчиненными регистратору.
Разберем по шагам правильный алгоритм работы:
Прочитать().Для Каждого ... Из ... Цикл и модифицируем необходимые ресурсы.Записать().Посмотрим на пример программного кода:
НаборЗаписейЗанятыхЯчеек = РегистрыСведений.ЗанятыеЯчейки.СоздатьНаборЗаписей();
// Устанавливаем отборы по измерениям
НаборЗаписейЗанятыхЯчеек.Отбор.ДатаНачала.Установить(Строка.ДатаНачала);
НаборЗаписейЗанятыхЯчеек.Отбор.ДатаОкончания.Установить(Строка.ДатаОкончания);
НаборЗаписейЗанятыхЯчеек.Отбор.Ячейка.Установить(Строка.Ячейка);
// Считываем записи из базы данных
НаборЗаписейЗанятыхЯчеек.Прочитать();
// Обходим прочитанные записи и меняем ресурсы
Для Каждого Запись Из НаборЗаписейЗанятыхЯчеек Цикл
Если Запись.СтоимостьЕдиницы = 0 Тогда
Запись.СтоимостьЕдиницы = Сумма;
КонецЕсли;
КонецЦикла;
// Записываем набор в базу данных
НаборЗаписейЗанятыхЯчеек.Записать();
Важное замечание: Метод Записать() по умолчанию выполняется с параметром Замещать = Истина. Это означает, что набор полностью перезаписывает данные в базе в рамках установленного отбора. Если отбор не был установлен вовсе, вызов Записать() приведет к полной очистке таблицы регистра сведений.
Если требуется прочитать и изменить ровно одну запись независимого регистра, удобно использовать РегистрСведенийМенеджерЗаписи. Разберем корректную реализацию этого механизма:
МенеджерЗаписи = РегистрыСведений.ЗанятыеЯчейки.СоздатьМенеджерЗаписи();
// Заполняем ВСЕ ключевые поля (измерения и период при наличии)
МенеджерЗаписи.Период = Строка.Период;
МенеджерЗаписи.ДатаНачала = Строка.ДатаНачала;
МенеджерЗаписи.ДатаОкончания = Строка.ДатаОкончания;
МенеджерЗаписи.Ячейка = Строка.Ячейка;
// Считываем конкретную запись
МенеджерЗаписи.Прочитать();
// Проверяем, существует ли запись в информационной базе
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.СтоимостьЕдиницы = Сумма;
МенеджерЗаписи.Записать(Истина);
КонецЕсли;
Метод Выбран() возвращает значение Истина, только если запись с указанными ключевыми полями была найдена в базе данных при вызове Прочитать().
Если регистр сведений подчинен регистратору, а корректировка записей выполняется в контексте документа (например, в процедуре ОбработкаПроведения модуля объекта), то правильнее всего работать напрямую с коллекцией Движения документа.
Рассмотрим пример заполнения или корректировки движений внутри модуля документа:
// Включаем флаг обязательной записи движений по регистру
Движения.ЗанятыеЯчейки.Записывать = Истина;
// Обходим уже сформированные движения документа
Для Каждого Движение Из Движения.ЗанятыеЯчейки Цикл
Если Движение.СтоимостьЕдиницы = 0 Тогда
Движение.СтоимостьЕдиницы = РассчитаннаяСумма;
КонецЕсли;
КонецЦикла;
Особенности работы с движениями документа:
Записывать = Истина сообщает платформе о необходимости сохранить сформированный набор движений в транзакции проведения документа.ПриЗакрытии) в обход проведения, так как при последующем штатном перепроведении документа эти изменения будут автоматически перезаписаны. Для актуализации данных подчиненных регистров следует вызывать полное перепроведение документа.