При интеграции 1С с внешними системами мобильной торговли или SFA (Sales Force Automation) часто возникает задача выгрузить данные о продажах и возвратах в текстовый файл строго определенного формата. При этом разработчики сталкиваются с рядом специфических ограничений языка запросов 1С, таких как невозможность получить строковое представление УникальныйИдентификатор или отформатировать дату непосредственно в самом запросе.
Разберем подробно, как правильно составить запрос, обойти ограничения платформы 1С:Предприятие и корректно сформировать итоговый файл выгрузки.
При выгрузке данных в сторонние сервисы мобильной коммерции часто встречаются специфические наименования полей. Выясним их значение в контексте структуры данных 1С:
Контрагенты, Партнеры или ДоговорыКонтрагентов (если адреса доставки привязаны к соглашениям).Пользователи либо кодом сотрудника из справочника ФизическиеЛица / Сотрудники.1 — продажа, 2 — возврат от покупателя).Проанализируем две частые проблемы, с которыми сталкиваются программисты при попытке выгрузить данные «чистым» запросом:
Формат() или прямые аналоги преобразования даты в строку вида YYYYMMDD. Функция ДАТАВРЕМЯ() служит только для задания констант, а функции ГОД(), МЕСЯЦ() и ДЕНЬ() возвращают числовые значения без ведущих нулей (например, месяц 2 вместо 02).УникальныйИдентификатор непосредственно в запросе нельзя. Платформа передает в выборку ссылку на объект (DocumentRef), а не его текстовый GUID.Оптимальным решением этих ограничений является постобработка данных при обходе выборки результата запроса.
Рассмотрим пошаговый пример построчного формирования текстового файла. В цикле обхода выборки применяется метод Формат() для даты и свойство УникальныйИдентификатор() для ссылочного поля документа.
// Создание текстового файла для выгрузки
ТекстПродажи = Новый ЗаписьТекста(ИмяФайлаПродажи, КодировкаТекста.UTF8);
// Записываем строку заголовка файла
ТекстПродажи.ЗаписатьСтроку(ЗагФайлаПродажи);
// Формируем запрос к регистру накопления
ЗапросПродаж = Новый Запрос;
ЗапросПродаж.Текст =
"ВЫБРАТЬ
| РеализацияТМЗОбороты.Номенклатура.Код КАК КодНоменклатуры,
| РеализацияТМЗОбороты.СтруктурноеПодразделение.Код КАК КодПодразделения,
| РеализацияТМЗОбороты.Партия.Автор.ФизЛицо.Код КАК КодАвтора,
| РеализацияТМЗОбороты.Регистратор КАК РегистраторСсылка,
| РеализацияТМЗОбороты.Период КАК ДатаДокумента,
| РеализацияТМЗОбороты.КоличествоОборот КАК Количество,
| РеализацияТМЗОбороты.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.РеализацияТМЗ.Обороты(&НачалоПериода, &КонецПериода, Регистратор, Организация = &Организация) КАК РеализацияТМЗОбороты";
ЗапросПродаж.УстановитьПараметр("НачалоПериода", НачалоПериода);
ЗапросПродаж.УстановитьПараметр("КонецПериода", КонецПериода);
ЗапросПродаж.УстановитьПараметр("Организация", Организация);
РезультатПродажи = ЗапросПродаж.Выполнить();
ВыборкаПродажи = РезультатПродажи.Выбрать();
// Построчно обрабатываем результат и записываем в файл
Пока ВыборкаПродажи.Следующий() Цикл
// Форматируем дату в вид YYYYMMDD (например, 20230115)
СтрокаДата = Формат(ВыборкаПродажи.ДатаДокумента, "ДФ=ггггММдд");
// Получаем строковый GUID из ссылки на документ
ИдентификаторДокумента = Строка(ВыборкаПродажи.РегистраторСсылка.УникальныйИдентификатор());
// Собираем строку с разделителями
СтрокаПродажи = ВыборкаПродажи.КодНоменклатуры + Разделитель
+ ВыборкаПродажи.КодПодразделения + Разделитель
+ ВыборкаПродажи.КодАвтора + Разделитель
+ СтрокаДата + Разделитель
+ ИдентификаторДокумента + Разделитель
+ ВыборкаПродажи.Количество + Разделитель
+ ВыборкаПродажи.Сумма;
ТекстПродажи.ЗаписатьСтроку(СтрокаПродажи);
КонецЦикла;
ТекстПродажи.Закрыть();
Если данные необходимо сначала подготовить в памяти, а затем передавать далее по коду, можно выгрузить результат запроса в объект ТаблицаЗначений и добавить вычисляемую колонку:
ТаблицаРезультата = ЗапросПродаж.Выполнить().Выгрузить();
ТаблицаРезультата.Колонки.Добавить("ПредставлениеДаты", Новый ОписаниеТипов("Строка"));
Для Каждого СтрокаРезультата Из ТаблицаРезультата Цикл
СтрокаРезультата.ПредставлениеДаты = Формат(СтрокаРезультата.ДатаДокумента, "ДФ=ггггММдд");
КонецЦикла;
Обратим внимание на важный аспект производительности при составлении запросов в 1С:
РеализацияТМЗОбороты.Партия.Автор.ФизЛицо.Код создает цепочку неявных левых соединений (LEFT JOIN) к базами данных СУБД. Если одно из полей окажется составного типа, это приведет к резкому падению скорости выполнения запроса.ЛЕВОЕ СОЕДИНЕНИЕ с нужным справочником по ссылке.Регистратор в виртуальной таблице оборотов, обязательно указывайте периодичность Регистратор в параметрах виртуальной таблицы: РегистрНакопления.РеализацияТМЗ.Обороты(&НачалоПериода, &КонецПериода, Регистратор, ...).