Как в Конвертации данных перенести только ту номенклатуру, по которой есть остатки и обороты?

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

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

Выбор правильной обработки для обмена данными

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

  1. Выгрузка и загрузка данных XML — внешняя или встроенная обработка, предназначенная исключительно для обмена между полностью идентичными конфигурациями. В ней нет возможности загрузить файл правил обмена, так как перенос осуществляется по прямому соответствию структуры метаданных.
  2. Универсальный обмен данными в формате XML — именно эта обработка работает с правилами обмена, созданными в конфигурации «Конвертация данных 2.1». Она входит в состав большинства типовых конфигураций или поставляется как внешняя обработка. На первой вкладке обязательно присутствует поле для выбора файла правил.

Для выполнения нашей задачи необходимо использовать именно «Универсальный обмен данными в формате XML».

Настройка правила выгрузки данных (ПВД)

Разберем по шагам, где и какой код необходимо прописать в конфигурации «Конвертация данных 2.1»:

  1. Перейдем на закладку «Правила выгрузки данных» и создадим новое правило (например, НоменклатураСДвижениями).
  2. Укажем способ выборки данных — «Произвольный алгоритм».
  3. В поле «Правило конвертации» выберем соответствующее ПКО для номенклатуры (например, Номенклатура).
  4. Откроем обработчик «Перед обработкой». Здесь формируется выборка объектов через обращение к регистрам накопления.

Проанализируем базовый вариант кода, при котором в специальную системную переменную ВыборкаДанных передается массив или список ссылок:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ОстаткиИОбороты.Номенклатура КАК Номенклатура
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, , , ) КАК ОстаткиИОбороты";

Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));

ВыборкаДанных = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Номенклатура");

В этом примере переменные ДатаНачала и ДатаОкончания передаются напрямую из формы обработки универсального обмена. Использование функции КонецДня() обязательно, так как дата окончания из реквизитов обработки часто поступает со временем 00:00:00, из-за чего движения за крайний день периода могут не попасть в выборку.

Оптимизация выборки и добавление отбора по складу

Если требуется получить номенклатуру только по определенному складу, крайне важно наложить фильтр непосредственно в параметрах виртуальной таблицы регистра, а не в секции ГДЕ. Это позволит СУБД рассчитать итоги только по нужному складу, не перегружая память сервера.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ТоварыОбороты.Номенклатура КАК Номенклатура
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, , , Склад = &Склад) КАК ТоварыОбороты";

Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));
Запрос.УстановитьПараметр("Склад", Параметры.СкладОтбора);

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

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

Альтернативный вариант: вызов функции «ВыгрузитьПоПравилу»

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	ОстаткиИОбороты.Номенклатура КАК Номенклатура
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&ДатаНачала, &ДатаОкончания, , , Склад = &Склад) КАК ОстаткиИОбороты";

Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));
Запрос.УстановитьПараметр("Склад", Параметры.Склад);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    ВыгрузитьПоПравилу(Выборка.Номенклатура, , , , "Номенклатура");
КонецЦикла;

Такой вариант удобен тем, что позволяет при необходимости передавать дополнительные исходящие параметры в ПКО или выполнять сложные дополнительные проверки по каждому элементу перед его выгрузкой.

Особенности выгрузки иерархии справочника

Обратим внимание на важное ограничение платформы: регистры накопления фиксируют движения только по элементам номенклатуры. Группы (папки) справочника в регистре не хранятся и, соответственно, в результат запроса к виртуальной таблице ОстаткиИОбороты не попадают.

Чтобы номенклатура в базе-приемнике не выгрузилась сплошным списком в корень справочника, необходимо проверить настройку правила конвертации объекта (ПКО) Номенклатура:

  1. В списке правил конвертации свойств (ПКС) для реквизита Родитель должно быть указано то же самое ПКО Номенклатура.
  2. При выгрузке ссылки элемента конвертация автоматически обратится к реквизиту Родитель и выгрузит иерархическую цепочку папок в приемник.
← На главную