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