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

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

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

В этой статье разберем, как программно скорректировать движения регистра накопления и заполнить новые поля напрямую через объект НаборЗаписей без инициации процедуры проведения.

Базовый принцип работы с набором записей

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

Посмотрим на базовую схему работы:


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

Для Каждого Запись Из НаборЗаписей Цикл
    Запись.НовоеИзмерение = Значение;
КонецЦикла;

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

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

Оптимальный алгоритм массовой обработки через запрос к регистру

Проанализируем частую ошибку: выборку документов через менеджер (например, Документы.ВнутреннийЗаказ.Выбрать()). Такой подход методически неверен по двум причинам:

  1. В выборку попадут непроведенные или помеченные на удаление документы, у которых нет движений по регистру.
  2. У одного регистра накопления может быть несколько различных документов-регистраторов (например, заказы, поступления, реализации, корректировки). Перебор конкретного вида документов пропустит остальные типы регистраторов.

Поэтому правильнее всего строить выборку «от регистратора», получая уникальный список документов прямым запросом к самому регистру накопления. Разберем реализацию этого подхода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    Регистр.Регистратор КАК Регистратор
    |ИЗ
    |    РегистрНакопления.ВнутренниеЗаказы КАК Регистр";

Выборка = Запрос.Выполнить().Выбрать();

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

Пока Выборка.Следующий() Цикл
    
    НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
    НаборЗаписей.Прочитать();
    
    Для Каждого СтрокаДвижения Из НаборЗаписей Цикл
        // Заполняем новое поле по требуемому прикладregisteredному алгоритму
        СтрокаДвижения.клПодразделениеПотребитель = СтрокаДвижения.Регистратор.ПодразделениеИсполнитель;
    КонецЦикла;
    
    // Отключаем обработчики и подписки для ускорения записи
    НаборЗаписей.ОбменДанными.Загрузка = Истина;
    НаборЗаписей.Записать();
    
КонецЦикла;

Важные технические нюансы при массовой перезаписи движений

Рассмотрим дополнительные аспекты производительности и целостности данных, о которых необходимо помнить при выполнении подобных корректировок на рабочих базах:

  1. Использование свойства ОбменДанными.Загрузка. Установка флага НаборЗаписей.ОбменДанными.Загрузка = Истина; перед вызовом метода Записать() отключает выполнение кода в модуле набора записей (в событиях ПередЗаписью и ПриЗаписи) и связанных подписках на события. Это существенно ускоряет процесс и предотвращает нежелательную регистрацию изменений в планах обмена распределенной информационной базы (РИБ).
  2. Обязательное обновление процедур проведения. Помните: ручная корректировка наборов записей обновляет только текущие данные. Если не внести соответствующие изменения в модуль документа (в процедуру ОбработкаПроведения), то при следующем штатном перепроведении документа пользователем новое измерение снова очистится или рассчитается по старому алгоритму.
  3. Управление пересчетом итогов на больших объемах данных. Каждая операция записи набора пересчитывает агрегатные таблицы итогов регистра. Если в регистре миллионы записей, рекомендуется временно отключить итоги, выполнить пакетную перезапись, а затем включить и пересчитать их:
    
    РегистрыНакопления.ВнутренниеЗаказы.УстановитьИспользованиеИтогов(Ложь);
    
    // ... Блок цикла обработки наборов записей ...
    
    РегистрыНакопления.ВнутренниеЗаказы.УстановитьИспользованиеИтогов(Истина);
    РегистрыНакопления.ВнутренниеЗаказы.ПересчитатьИтоги();
    
  4. Транзакции и порционная обработка. При обработке больших массивов информации во избежание разрастания журнала транзакций СУБД и блокировок рекомендуется фиксировать изменения порциями (например, пакетами по 500–1000 регистраторов) с помощью операторов НачатьТранзакцию() и ЗафиксироватьТранзакцию().
← На главную