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