Как вывести штрихкоды номенклатуры в иерархический макет при выгрузке в Excel

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

При разработке отчетов или обработок выгрузки часто возникает задача вывода данных, имеющих сложную иерархическую структуру. Типичный пример — справочник номенклатуры, где необходимо отобразить не только сами папки и товары, но и подчиненные им сущности, такие как варианты исполнения (характеристики) и соответствующие им штрихкоды. В процессе реализации программисты часто сталкиваются с тем, что параметры макета заполняются некорректно, значения «перетекают» из одной строки в другую, а рекурсия отрабатывает не на всех уровнях.

В этой статье мы подробно разберем, как правильно организовать вывод иерархии в табличный документ, как динамически формировать штрихкоды и как избежать типичных ошибок при работе с параметрами макета 1С.

Анализ проблемы: почему данные не выводятся

Рассмотрим типичную ситуацию. В запросе используются ИТОГИ ПО Номенклатура ИЕРАРХИЯ. При обходе такой выборки важно понимать, что каждая запись может быть либо группой (папкой), либо элементом. Если мы пытаемся получить штрихкод для группы, у которой нет владельца-номенклатуры в контексте подчиненного справочника, мы получим Неопределено.

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

Шаг 1. Подготовка запроса и основной процедуры

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


Процедура ВыгрузитьШаблон(ВхСтрокаКонтрагент)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ВариантыИсполнения.Владелец КАК Номенклатура,
        |   ВариантыИсполнения.Ссылка КАК ВИ
        |ИЗ
        |   Справочник.ВариантыИсполнения КАК ВариантыИсполнения
        |ГДЕ
        |   ВариантыИсполнения.ПометкаУдаления = ЛОЖЬ
        |   И ВариантыИсполнения.Владелец В ИЕРАРХИИ(&Номенклатура)
        |ИТОГИ ПО
        |   Номенклатура ИЕРАРХИЯ";
        
    Запрос.УстановитьПараметр("Номенклатура", СписокНоменклатуры);
    
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДетали = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    
    ТабДок = Новый ТабличныйДокумент;
    Макет = ПолучитьМакет("Макет");
    ОбластьСтрока = Макет.ПолучитьОбласть("Тело");
    
    ТабДок.НачатьАвтогруппировкуСтрок();
    РекурсивныйВыводСтрок(ТабДок, ОбластьСтрока, ВыборкаДетали);
    ТабДок.ЗакончитьАвтогруппировкуСтрок();
    
    ТабДок.Показать();
КонецПроцедуры

Шаг 2. Реализация правильной рекурсии

Теперь разберем саму процедуру РекурсивныйВыводСтрок. Главная задача здесь — разделять логику вывода родительских узлов (групп) и детальных записей (товаров с их вариантами). Мы должны проверять свойство ЭтоГруппа и, если это не группа, выполнять вложенный цикл по результатам группировки для вывода всех вариантов исполнения.

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


Процедура РекурсивныйВыводСтрок(ТабДок, ОбластьСтрока, ВыборкаДетали)
    Пока ВыборкаДетали.Следующий() Цикл
        // Заполняем основные параметры (Наименование, Код номенклатуры)
        ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, ВыборкаДетали);
        
        // Выводим строку в табличный документ с указанием уровня иерархии
        ТабДок.Вывести(ОбластьСтрока, ВыборкаДетали.Уровень());
        
        // Получаем вложенную выборку
        ВыборкаРезультат = ВыборкаДетали.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
        
        Если ВыборкаДетали.Номенклатура.ЭтоГруппа Тогда
            // Если это папка, уходим глубже в рекурсию
            РекурсивныйВыводСтрок(ТабДок, ОбластьСтрока, ВыборкаРезультат);
        Иначе
            // Если это товар, обходим его варианты исполнения (характеристики)
            Пока ВыборкаРезультат.Следующий() Цикл
                Если ЗначениеЗаполнено(ВыборкаРезультат.ВИ) Тогда
                    _Дополнительно = Новый Структура;
                    _Дополнительно.Вставить("ВариантИсполнения", ВыборкаРезультат.ВИ);
                    _Дополнительно.Вставить("ЕдИзм", ВыборкаРезультат.Номенклатура.БазоваяЕдИзм);
                    
                    // Вызываем функцию формирования ШК
                    _ШК = глСформироватьВнутреннийШтрихкод(ВыборкаРезультат.Номенклатура, _Дополнительно);
                    
                    // Заполняем специфические параметры макета
                    ОбластьСтрока.Параметры.ВариантИсполнения = ВыборкаРезультат.ВИ;
                    ОбластьСтрока.Параметры._ШК = _ШК;
                    
                    // Выводим строку варианта на уровень глубже самого товара
                    ТабДок.Вывести(ОбластьСтрока, ВыборкаДетали.Уровень() + 1);
                    
                    // ОЧИСТКА ПАРАМЕТРОВ: очень важный момент!
                    ОбластьСтрока.Параметры.ВариантИсполнения = "";
                    ОбластьСтрока.Параметры._ШК = "";
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Шаг 3. Очистка параметров макета

Рассмотрим подробнее проблему «фантомных» данных. В 1С объекты областей макета, полученные через ПолучитьОбласть, сохраняют значения параметров между вызовами метода Вывести(). Если для первой строки товара вы заполнили параметр ВариантИсполнения, а для второй (которая является просто папкой) — нет, то в печатную форму может подставиться значение из предыдущей строки.

Существует два способа решения этой проблемы:

  1. Ручное зануление: После каждого метода Вывести() явно присваивать параметрам пустые значения, как показано в примере выше.
  2. Переполучение области: В начале цикла заново вызывать ОбластьСтрока = Макет.ПолучитьОбласть("Тело"). Это гарантирует, что параметры будут чистыми, но может незначительно замедлить работу при очень больших объемах данных.

Шаг 4. Логика формирования внутреннего штрихкода

Зачастую на предприятиях используются внутренние алгоритмы генерации штрихкодов. Рассмотрим пример функции, которая собирает код формата EAN-like на основе кодов номенклатуры и характеристик. Это поможет нам понять, какие данные должны быть в структуре _Дополнительно.


Функция глСформироватьВнутреннийШтрихкод(ВхВладелец, ВхДополнительно) Экспорт
    _НовыйШтрихкод = "";
    
    // Получаем данные из структуры
    ВхВариантИсполнения = Неопределено;
    ВхДополнительно.Свойство("ВариантИсполнения", ВхВариантИсполнения);
    
    Если ТипЗнч(ВхВладелец) = Тип("СправочникСсылка.Номенклатура") Тогда
        // Префикс 20 для внутренних ШК
        _НовыйШтрихкод = "20" + Формат(ВхВладелец.Код, "ЧЦ=9; ЧВН=; ЧГ=0");
        
        // Добавляем код варианта (6 знаков)
        Если ВхВариантИсполнения <> Неопределено Тогда
            _НовыйШтрихкод = _НовыйШтрихкод + Формат(ВхВариантИсполнения.Код, "ЧЦ=6; ЧВН=; ЧГ=0");
        Иначе
            _НовыйШтрихкод = _НовыйШтрихкод + "000000";
        КонецЕсли;
    КонецЕсли;
    
    Возврат _НовыйШтрихкод;
КонецФункции

Шаг 5. Сохранение в Excel без ошибок формата

Завершающим этапом является запись полученного табличного документа в файл. Пользователи часто сталкиваются с сообщением Excel: «Действительный формат открываемого файла отличается от указываемого...». Это происходит, если расширение файла (например, .xls) не совпадает с внутренним форматом сохранения 1С.

Разберем, как правильно сохранить файл, используя путь из реквизита формы:


// Предположим, КаталогШаблонов - путь к папке, выбранный пользователем
ПолноеИмяФайла = КаталогШаблонов + "\ШаблонЗаказа_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd") + ".xlsx";

// Обязательно указываем второй параметр - ТипФайлаТабличногоДокумента
ТабДок.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLSX);

Сообщить("Файл успешно сохранен: " + ПолноеИмяФайла);

Использование формата XLSX (OpenXML) является наиболее предпочтительным для современных версий Microsoft Excel, так как он обеспечивает корректную работу с цветами, шрифтами и большими объемами строк без потери данных.

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

← На главную