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