В платформе 1С:Предприятие 7.7, особенно в конфигурации «Торговля и Склад 9.2», работа со свойствами объектов реализована через механизм подчиненных справочников. Часто возникает задача отфильтровать товары по определенному свойству (например, «Выгружать на сайт») и получить по ним актуальные остатки для передачи во внешние системы через CSV или HTTP-запросы. Разберем по шагам, как это реализовать эффективно.
Прежде чем приступать к написанию кода, проанализируем, как данные хранятся в базе. В типовой конфигурации «Торговля и Склад» существует основной справочник Номенклатура. Ему подчинен справочник СвойстваНоменклатуры. Каждая запись в этом справочнике содержит:
Номенклатура.ВидыСвойств (например, запись «На сайт»).ЗначенияСвойств (например, «Да» или «Нет»).Для решения задачи нам необходимо найти все записи в справочнике СвойстваНоменклатуры, у которых вид и значение соответствуют нашим критериям, и получить их владельцев.
Рассмотрим наиболее производительный способ — использование внутреннего языка запросов 1С 7.7. Вместо того чтобы перебирать весь справочник Номенклатура и для каждого товара проверять его свойства (что приведет к огромному количеству обращений к базе), мы обратимся напрямую к справочнику свойств.
Проанализируем пример кода для реализации фильтрации:
Процедура ВыгрузитьТоварыПоСвойству()
Перем Запрос, ТекстЗапроса;
// Создаем объект Запрос
Запрос = СоздатьОбъект("Запрос");
// Настраиваем текст запроса
// Мы выбираем Владельца (товар), фильтруя по Виду и Значению свойства
ТекстЗапроса =
"//{{ЗАПРОС(ВыгрузитьТоварыПоСвойству)
|Без итогов;
|ТМЦ = Справочник.СвойстваНоменклатуры.Владелец;
|Вид = Справочник.СвойстваНоменклатуры.ВидСвойства;
|Значение = Справочник.СвойстваНоменклатуры.ЗначениеСвойства;
|Группировка ТМЦ без групп;
|Условие(Вид = ВыбВидСвойства);
|Условие(Значение = ВыбЗначениеСвойства);
|"//}}ЗАПРОС
;
// Выполняем запрос
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
// Перебираем результаты
Пока Запрос.Группировка(1) = 1 Цикл
// Здесь мы получили конкретный товар, подходящий под фильтр
Товар = Запрос.ТМЦ;
Сообщить("Выгружаем: " + Товар.Наименование);
// Далее можно вызывать функцию получения остатка
КонецЦикла;
КонецПроцедуры
В этом примере ВыбВидСвойства и ВыбЗначениеСвойства — это ссылки на соответствующие элементы справочников, которые вы можете выбрать на форме или найти программно через НайтиПоНаименованию.
Если нам нужно проверить свойства конкретного товара в процессе цикла по номенклатуре, мы можем воспользоваться методом ИспользоватьВладельца(). Выясним, как это работает на практике. Этот метод ограничивает выборку справочника только теми элементами, которые принадлежат конкретному объекту-владельцу.
СпрСвойства = СоздатьОбъект("Справочник.СвойстваНоменклатуры");
СпрСвойства.ИспользоватьВладельца(ТекущийТовар);
СпрСвойства.ВыбратьЭлементы();
Пока СпрСвойства.ПолучитьЭлемент() = 1 Цикл
Если (СпрСвойства.ВидСвойства = НужныйВид) и (СпрСвойства.ЗначениеСвойства = НужноеЗначение) Тогда
// Товар подходит под условие
Прервать;
КонецЕсли;
КонецЦикла;
Важно: этот метод крайне медленный, если товаров в базе много (более 1000), так как для каждой позиции 1С будет выполнять отдельный SQL-запрос к таблице свойств.
После того как мы отфильтровали нужные товары, нам необходимо получить их остатки. В 1С 7.7 для этого используется объект Регистр.ОстаткиТМЦ. Рассмотрим, как получить сводный остаток по всем складам для конкретной позиции.
Функция ПолучитьОстатокТовара(Товар)
Рег = СоздатьОбъект("Регистр.ОстаткиТМЦ");
Возврат Рег.СводныйОстаток(Товар, , , "Количество");
КонецФункции
Однако, если вы делаете массовую выгрузку, эффективнее будет один раз выгрузить все итоги регистра в таблицу значений методом ВыгрузитьИтоги(), а затем искать в этой таблице данные по коду или ссылке товара. Это значительно ускорит работу обработки.
Для записи данных в формате CSV в 1С 7.7 используется объект Текст. Проанализируем нюансы: штатный метод Записать() сохраняет файл в кодировке Windows-1251. Если ваш сайт требует UTF-8, придется использовать внешние компоненты или объект ADODB.Stream.
Пример формирования строки CSV:
ТекстФайла = СоздатьОбъект("Текст");
// Заголовок CSV
ТекстФайла.ДобавитьСтроку("Артикул;Наименование;Остаток");
// В цикле по запросу
СтрокаДанных = СокрЛП(Товар.Артикул) + ";" + СокрЛП(Товар.Наименование) + ";" + Строка(Остаток);
ТекстФайла.ДобавитьСтроку(СтрокаДанных);
// Сохранение
ТекстФайла.Записать("C:\export\items.csv");
Если задача стоит сделать выгрузку «молча» и отправить её на сервер, рассмотрим использование объекта WinHttp.WinHttpRequest.5.1. Это позволит отправить данные методом POST без участия пользователя.
Http = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
Http.Open("POST", "https://vash-sayt.ru/api/update", 0);
Http.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// Подготовка тела запроса
ТелоЗапроса = "data=" + ДанныеДляОтправки;
Http.Send(ТелоЗапроса);
Если Http.Status = 200 Тогда
Сообщить("Данные успешно отправлены");
КонецЕсли;
Для реализации задачи «минимум» (получение свойств) лучше всего подходит объект Запрос к справочнику свойств. Для задачи «максимум» (автоматическая выгрузка) необходимо комбинировать запрос к свойствам, выгрузку итогов регистров в таблицу значений для скорости и объект WinHttp для передачи данных на сервер. Не забывайте проверять реквизит ЭтоГруппа() при переборе номенклатуры, чтобы исключить папки из процесса получения остатков.