Как вывести макет ценника на страницу в три строки по три колонки в 1С?

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

При работе с печатными формами в 1С, особенно когда речь идет о ценниках или этикетках, часто возникает задача вывести несколько одинаковых или схожих макетов на один лист, формируя аккуратную сетку. Рассмотрим ситуацию, когда требуется вывести ценники номенклатуры в формате 3x3 на листе А4, используя при этом один макет.

Представим, что у нас уже есть готовый макет ценника, который корректно заполняется данными по одной номенклатуре и выводится в табличный документ. Изначально этот макет выводится "в одну колонку и вниз", что не соответствует нашим требованиям. Наша цель – заполнить макет в цикле N раз таким образом, чтобы на листе А4 было три ценника по горизонтали и три по вертикали, то есть всего шесть ценников на лист (примечание: в исходном вопросе указано "три по горизонтали на три по вертикали (итого на А4 6 ценников номенклатур)", что может быть ошибкой в подсчете, так как 3х3=9 ценников. Мы будем ориентироваться на формирование сетки, подразумевая, что количество ценников может быть любым, но принцип построения сетки остается тем же).

Понимание проблемы и поиск решения

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

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

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

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

Детальный алгоритм формирования сетки 3x3

Рассмотрим по шагам, как реализовать вывод ценников в формате 3x3 на листе А4, используя один макет.

  1. Инициализация табличного документа и макета: В начале функции нам потребуется создать новый объект ТабличныйДокумент, который будет служить нашей печатной формой, и получить нужный макет из обработки или отчета.
  2. Обход данных и заполнение ценников: Мы будем итерироваться по коллекции данных (например, таблице значений с номенклатурой), для каждой записи заполняя параметры макета ценника.
  3. Формирование горизонтальных рядов (колонки) с помощью Присоединить: Внутри основного цикла по номенклатуре нам понадобится внутренний счетчик, который будет отслеживать, сколько ценников уже добавлено в текущий горизонтальный ряд. Мы будем использовать метод Присоединить для добавления ценников справа, пока не достигнем нужного количества (в нашем случае – 3 ценника).
  4. Переход на новую строку с помощью Вывести: Как только горизонтальный ряд заполнен (то есть 3 ценника присоединены), нам нужно "перевести каретку" на новую строку. Для этого мы создадим временный табличный документ, в который собрали только что сформированную горизонтальную строку ценников, а затем выведем этот временный табличный документ в основной с помощью метода Вывести. Это обеспечит переход на следующую строку.
  5. Обработка оставшихся ценников: Если после формирования всех полных строк остались ценники, которых недостаточно для заполнения целой строки, их также нужно вывести в последнюю неполную строку.
  6. Управление страницами: Для того чтобы ценники не выходили за пределы листа А4 и корректно разбивались на страницы, необходимо использовать методы контроля вывода, такие как ПроверитьВывод() и ПроверитьПрисоединение().

Пример кода для реализации

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


&НаСервере
Функция СформироватьПечатнуюФорму(Таблиц1)

    // Основной табличный документ, куда будут выводиться все ценники
    ТабличныйДокументИтоговый = Новый ТабличныйДокумент;
    ТабличныйДокументИтоговый.АвтоМасштаб = Истина;
    
    // Получаем макет обработки
    Обработка = РеквизитФормыВЗначение("Объект");
    МакетОбработки = Обработка.ПолучитьМакет("Макет");
    
    // Переменные для управления выводом в сетку
    КонтрКолонокНаСтранице = 3; // Количество ценников по горизонтали
    КонтрСтрокНаСтранице = 3;  // Количество ценников по вертикали
    СчетчикТекущейКолонки = 0;
    СчетчикТекущейСтроки = 0;
    
    // Временный табличный документ для сборки текущей строки ценников
    // Перед выводом в ТабличныйДокументИтоговый он будет очищаться
    ТабличныйДокументСтрока = Новый ТабличныйДокумент;

    Для Каждого ТекущаяСтрока Из Таблиц1 Цикл
        
        // Получаем область макета ценника
        ОбластьЦенника = МакетОбработки.ПолучитьОбласть("ОбластьЦенника"); // Предполагаем, что имя области 'ОбластьЦенника'

        // Заполнение параметров ценника
        ОбластьЦенника.Параметры.Описание = ТекущаяСтрока.Номенклатура.Описание;
        ОбластьЦенника.Параметры.Цена = ТекущаяСтрока.Цена; // Добавим для примера
        
        // Заполнение картинки (фото)
        ФайлКартинки = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ТекущаяСтрока.Номенклатура, "ФайлКартинки");
        Если ЗначениеЗаполнено(ФайлКартинки.Наименование) Тогда
            ДвоичныеДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(ФайлКартинки);
            Картинка = Новый Картинка();
            Если ТипЗнч(ДвоичныеДанныеФайла) = Тип("Картинка") Тогда
                Картинка = ДвоичныеДанныеФайла;
            ИначеЕсли ТипЗнч(ДвоичныеДанныеФайла) = Тип("ДвоичныеДанные") Тогда
                Картинка = Новый Картинка(ДвоичныеДанныеФайла);
            КонецЕсли;
            ОбластьЦенника.Параметры.Фото1 = Картинка;
        КонецЕсли;
        
        // Заполнение штрихкода
        ЗначениеШтрихкода = "1111234567890"; // Пример штрихкода
        Если ЗначениеЗаполнено(ЗначениеШтрихкода) Тогда
            ПараметрыШтрихкода = Новый Структура;
            ПараметрыШтрихкода.Вставить("Ширина", 90);
            ПараметрыШтрихкода.Вставить("Высота", 40);
            ПараметрыШтрихкода.Вставить("Штрихкод", ЗначениеШтрихкода);
            ПараметрыШтрихкода.Вставить("ТипКода", "EAN13");
            ПараметрыШтрихкода.Вставить("ОтображатьТекст", Ложь);
            КартинкаШКСфоримровать = МенеджерОборудованияВызовСервера.ПолучитьКартинкуШтрихкода(ПараметрыШтрихкода);
            Если КартинкаШКСфоримровать <> Неопределено Тогда
                ОбластьЦенника.Рисунки.КартинкаШК.Картинка = КартинкаШКСфоримровать;
            КонецЕсли;
        КонецЕсли;
        
        // --- Логика формирования сетки ---
        
        // Проверяем, помещается ли текущий ценник по горизонтали
        Если СчетчикТекущейКолонки = 0 Тогда
            // Если это первый ценник в строке, просто выводим его во временный документ строки
            ТабличныйДокументСтрока.Очистить(); // Очищаем временный документ для новой строки
            ТабличныйДокументСтрока.Вывести(ОбластьЦенника);
        Иначе
            // Если уже есть ценники в строке, присоединяем справа
            ТабличныйДокументСтрока.Присоединить(ОбластьЦенника);
        КонецЕсли;
        
        СчетчикТекущейКолонки = СчетчикТекущейКолонки + 1;
        
        // Если заполнили всю горизонтальную строку (КонтрКолонокНаСтранице ценников)
        Если СчетчикТекущейКолонки = КонтрКолонокНаСтранице Тогда
            // Выводим собранную строку ценников в основной документ
            ТабличныйДокументИтоговый.Вывести(ТабличныйДокументСтрока);
            СчетчикТекущейСтроки = СчетчикТекущейСтроки + 1;
            СчетчикТекущейКолонки = 0; // Сбрасываем счетчик колонок для новой строки
            
            // Проверяем, не достигли ли мы предела строк на странице
            Если СчетчикТекущейСтроки = КонтрСтрокНаСтранице Тогда
                ТабличныйДокументИтоговый.НоваяСтраница(); // Переходим на новую страницу
                СчетчикТекущейСтроки = 0; // Сбрасываем счетчик строк для новой страницы
            КонецЕсли;
        КонецЕсли;
        
    КонецЦикла;
    
    // Если после цикла остались невыведенные ценники в ТабличныйДокументСтрока (неполная последняя строка)
    Если СчетчикТекущейКолонки > 0 Тогда
        ТабличныйДокументИтоговый.Вывести(ТабличныйДокументСтрока);
    КонецЕсли;
    
    Возврат ТабличныйДокументИтоговый;
    
КонецФункции

Важные моменты в приведенном коде:

  1. Мы используем два объекта ТабличныйДокумент: ТабличныйДокументИтоговый для всей печатной формы и ТабличныйДокументСтрока для временного хранения ценников, которые будут формировать одну горизонтальную строку.
  2. Переменные КонтрКолонокНаСтранице и КонтрСтрокНаСтранице определяют желаемый размер сетки.
  3. Внутри цикла по данным мы сначала заполняем параметры для одного ценника в ОбластьЦенника.
  4. Затем, если это первый ценник в текущем горизонтальном ряду (СчетчикТекущейКолонки = 0), мы используем ТабличныйДокументСтрока.Вывести(ОбластьЦенника). Это как бы "инициализирует" новую временную строку для горизонтального присоединения. При этом важно очистить ТабличныйДокументСтрока перед первой Вывести в новой строке.
  5. Для последующих ценников в той же горизонтальной строке (СчетчикТекущейКолонки > 0) мы используем ТабличныйДокументСтрока.Присоединить(ОбластьЦенника). Это добавляет ценник справа от предыдущего в рамках временного документа ТабличныйДокументСтрока.
  6. Когда СчетчикТекущейКолонки достигает значения КонтрКолонокНаСтранице, это означает, что одна полная горизонтальная строка ценников сформирована во временном документе ТабличныйДокументСтрока. Мы выводим этот собранный временный документ в основной ТабличныйДокументИтоговый методом ТабличныйДокументИтоговый.Вывести(ТабличныйДокументСтрока). Это автоматически переводит нас на новую строку в основном документе.
  7. После вывода полной строки, сбрасываем СчетчикТекущейКолонки в 0 и увеличиваем СчетчикТекущейСтроки.
  8. Мы также проверяем, не достигли ли мы предела строк на текущей странице (СчетчикТекущейСтроки = КонтрСтрокНаСтранице) и при необходимости вызываем ТабличныйДокументИтоговый.НоваяСтраница() для принудительного перехода на новый лист.
  9. Наконец, после основного цикла, мы проверяем, не осталась ли неполная строка ценников (СчетчикТекущейКолонки > 0) и, если да, выводим ее в ТабличныйДокументИтоговый.

Управление разбиением на страницы и количеством ценников

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

  1. ПроверитьВывод(Область): Этот метод позволяет проверить, поместится ли указанная область на текущую страницу табличного документа. Если нет, то он автоматически переходит на новую страницу. Мы можем использовать его перед вызовом ТабличныйДокументИтоговый.Вывести(ТабличныйДокументСтрока), чтобы гарантировать корректное разбиение строк на страницы.
  2. ПроверитьПрисоединение(Область): Аналогично, этот метод проверяет, поместится ли область при присоединении по горизонтали, и при необходимости может инициировать переход на новую страницу или изменить форматирование. Однако для простой сетки 3x3 обычно достаточно контроля по строкам, а ширину макета ценника мы предполагаем постоянной.

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

Особенности работы с форматами строк

Важно помнить, что ТабличныйДокумент может использовать различную ширину колонок для разных строк. Если области макета, которые вы присоединяете, имеют разную ширину, это может привести к непредсказуемому форматированию. Мы рекомендуем:

Общие рекомендации при формировании печатных форм

При разработке и отладке печатных форм:

  1. Мы рекомендуем сначала формировать табличный документ и отображать его пользователю для предварительного просмотра. Это позволяет быстро проверить корректность вывода, прежде чем отправлять документ на принтер.
  2. Учитывайте производительность при работе с очень большим количеством ценников. Эффективность запросов к базе данных и оптимизация работы с картинками могут существенно сократить время формирования печатной формы.
  3. При использовании параметров в макете (например, <Описание>), убедитесь, что они явно назначены через коллекцию Параметры объекта ОбластьМакета.

Таким образом, комбинируя методы Присоединить и Вывести, мы можем эффективно управлять расположением областей макета на листе, создавая сложные и гибкие печатные формы, такие как сетки ценников, полностью адаптированные под наши нужды.

← На главную