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