Как программно заполнить документ «Корректировка записей регистров» результатами запроса в 1С?

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

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

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

Для понимания механизма заполнения важно учитывать особенности архитектуры документа корректировки в типовых конфигурациях:

  1. Работа через наборы записей: Данные по регистрам хранятся не в типовых табличных частях документа, а в коллекции Движения объекта документа, где каждый регистр представлен собственным набором записей.
  2. Служебные табличные части: В ряде конфигураций (например, УПП 1.3 или Комплексная автоматизация 1.1) видимость закладок в форме документа определяется составом строк в служебных табличных частях: ТаблицаРегистровНакопления, ТаблицаРегистровБухгалтерии и ТаблицаРегистровСведений. Если добавить записи в движения, но не заполнить имя регистра в служебной таблице, пользователь может не увидеть сформированные движения при открытии формы.
  3. Режим записи: Документ корректировки обычно не требует проведения в оперативном режиме — сохранение движений выполняется при обычной записи с установленным признаком Записывать = Истина у набора записей.

Способ 1. Быстрая загрузка таблицы значений в набор записей

Рассмотрим самый быстрый способ переноса данных — метод Загрузить() набора записей. Метод принимает на вход таблицу значений, полученную из результата запроса с помощью РезультатЗапроса.Выгрузить().

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

  1. Период — дата движения (тип Дата).
  2. ВидДвижения — для регистров накопления (значение системного перечисления ВидДвиженияНакопления.Приход или ВидДвиженияНакопления.Расход).

Посмотрим на пример кода заполнения регистра накопления «ВзаиморасчетыСКонтрагентами»:


// Получаем объект документа по ссылке
ДокОбъект = СсылкаНаКорректировку.ПолучитьОбъект();

// Выполняем заранее подготовленный запрос
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДанных = РезультатЗапроса.Выгрузить();

// Добавляем регистр в служебную таблицу для отображения в интерфейсе
СтрокаТаблицыРегистров = ДокОбъект.ТаблицаРегистровНакопления.Найти("ВзаиморасчетыСКонтрагентами", "Имя");
Если СтрокаТаблицыРегистров = Неопределено Тогда
    СтрокаТаблицыРегистров = ДокОбъект.ТаблицаРегистровНакопления.Добавить();
    СтрокаТаблицыРегистров.Имя = "ВзаиморасчетыСКонтрагентами";
КонецЕсли;

// Получаем набор записей регистра из движений документа
НаборЗаписей = ДокОбъект.Движения.ВзаиморасчетыСКонтрагентами;

// Загружаем данные из таблицы значений
НаборЗаписей.Загрузить(ТаблицаДанных);

// Указываем флаг обязательной записи набора вместе с документом
НаборЗаписей.Записывать = Истина;

// Сохраняем документ
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Способ 2. Построчное заполнение через выборку запроса

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


ДокОбъект = СсылкаНаКорректировку.ПолучитьОбъект();

// Обеспечиваем отображение закладки регистра
Если ДокОбъект.ТаблицаРегистровНакопления.Найти("ВзаиморасчетыСКонтрагентами", "Имя") = Неопределено Тогда
    НоваяСтрока = ДокОбъект.ТаблицаРегистровНакопления.Добавить();
    НоваяСтрока.Имя = "ВзаиморасчетыСКонтрагентами";
КонецЕсли;

НаборЗаписей = ДокОбъект.Движения.ВзаиморасчетыСКонтрагентами;

// Если нужно сохранить уже имеющиеся строки в документе, сначала считываем их:
// НаборЗаписей.Прочитать();

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

НаборЗаписей.Записывать = Истина;
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);

Частые ошибки при заполнении наборов записей

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

  1. Перезапись существующих движений: Метод Загрузить() полностью очищает набор записей перед вставкой строк. Если в документе уже были движения по этому регистру и их требовалось дополнить, а не затереть, необходимо использовать предварительный вызов НаборЗаписей.Прочитать() и построчное добавление через метод Добавить().
  2. Несовпадение типов: Если поле в запросе содержит NULL или тип, не включенный в составной тип измерения регистра, метод Загрузить() вызовет исключение при попытке записи. Все поля выборки запроса должны быть явно приведены к типам метаданных через ВЫРАЗИТЬ(...) или функции ЕСТЬNULL(...).
  3. Запись открытого документа: Если обработка пытается изменить документ, открытый в этот момент пользователем в интерфейсе, возникнет конфликт блокировок или рассинхронизация данных формы и базы данных. Перед модификацией документа на сервере необходимо закрывать форму документа или передавать данные в саму форму для интерактивной обработки.
← На главную