Как открыть несколько печатных форм одного или разных документов в одном окне табличного документа в 1С (обычное приложение)? Мы часто сталкиваемся с задачей, когда необходимо сформировать несколько печатных форм различных документов или одного типа документов за определенный период и представить их в одном объединенном табличном документе. Стандартный подход, когда каждая печатная форма открывается в отдельном окне, может быть неудобен, если требуется просмотреть или распечатать их все последовательно. Давайте разберем, как решить эту задачу, объединив все печатные формы в единый табличный документ.

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

Основное решение: модификация функции "Печать()" и последовательное объединение

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

Шаг 1: Превращаем процедуру "Печать()" в функцию

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

Было:


Процедура Печать()
    // ... логика формирования ТабДок
    ТабДок.Показать();
КонецПроцедуры

Стало:


Функция Печать() Экспорт // Делаем функцию экспортной, если она вызывается извне модуля объекта
    ТабДок = Новый ТабличныйДокумент;
    // ... Ваша логика формирования ТабДок
    // ТабДок.Вывести(ОбластьМакета);
    // ...
    Возврат ТабДок;
КонецФункции

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

Шаг 2: Создаем итоговый табличный документ и собираем в него все формы

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


Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Определяем период, за который нам нужны документы
    ДатаНачала = '20230101'; // Пример: начало года
    ДатаОкончания = ТекущаяДата(); // Пример: текущая дата

    // Выбираем документы, которые будем печатать.
    // В данном случае, это документы "ПродажаТоваров".
    Выборка = Документы.ПродажаТоваров.Выбрать(ДатаНачала, КонецДня(ДатаОкончания));

    // Создаем новый, пустой табличный документ, куда будем собирать все печатные формы
    ИтоговыйТабДок = Новый ТабличныйДокумент;

    Пока Выборка.Следующий() Цикл
        // Получаем объект документа из выборки.
        // Это важно, так как метод Печать() обычно является методом объекта документа.
        оДок = Выборка.ПолучитьОбъект();

        // Вызываем нашу модифицированную функцию Печать() для текущего документа.
        // Она возвращает готовый ТабличныйДокумент для этого конкретного документа.
        ТД = оДок.Печать();

        // Выводим полученный ТабличныйДокумент в наш итоговый документ.
        ИтоговыйТабДок.Вывести(ТД);

        // Добавляем горизонтальный разделитель страниц после каждой печатной формы.
        // Это гарантирует, что каждая новая форма начнется с новой страницы при печати.
        ИтоговыйТабДок.ВывестиГоризонтальныйРазделительСтраниц();

        // Опционально: отключаем отображение сетки для более чистого вида.
        ИтоговыйТабДок.ОтображатьСетку = Ложь;
    КонецЦикла;

    // После того как все печатные формы собраны, показываем итоговый табличный документ.
    ИтоговыйТабДок.Показать();
КонецПроцедуры

В этом примере мы видим, как с помощью цикла Пока Выборка.Следующий() Цикл мы перебираем необходимые документы. Для каждого документа мы получаем его объект методом ПолучитьОбъект(), вызываем нашу функцию Печать(), и затем методом Вывести() объекта ИтоговыйТабДок добавляем его содержимое. Метод ВывестиГоризонтальныйРазделительСтраниц() очень важен, так как он обеспечивает корректное разбиение на страницы при печати. Наконец, после цикла, мы однократно вызываем Показать() для итогового документа.

Учет различных форматов колонок при объединении

При объединении нескольких табличных документов, особенно если они формируются из разных макетов или имеют разную структуру колонок, может возникнуть проблема "разъезжания" или смещения колонок. Метод Вывести() по умолчанию пытается "приспособить" выводимую область к формату текущего табличного документа, что не всегда желательно. Чтобы сохранить исходную ширину и форматирование колонок каждой вставляемой печатной формы, мы можем использовать метод СоздатьФорматСтрок(). Рассмотрим подробнее, как это работает:

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

Вот как мы можем скорректировать цикл объединения:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    // ... (начало такое же, как в предыдущем примере)
    Выборка = Документы.ПродажаТоваров.Выбрать(ДатаНачала, КонецДня(ДатаОкончания));
    ИтоговыйТабДок = Новый ТабличныйДокумент;

    Пока Выборка.Следующий() Цикл
        оДок = Выборка.ПолучитьОбъект();
        ТД = оДок.Печать(); // Получаем ТабличныйДокумент для текущего документа

        // Создаем временный табличный документ для обработки текущей формы
        ВременныйТабДок = Новый ТабличныйДокумент;
        ВременныйТабДок.Вывести(ТД); // Выводим полученную форму во временный документ

        // Получаем область, которую мы только что вывели во временный документ
        // (обычно это весь документ, если он небольшой, или конкретная область)
        ОбластьДляВывода = ВременныйТабДок.Область(1, 1, ВременныйТабДок.ВысотаТаблицы, ВременныйТабДок.ШиринаТаблицы);

        // Создаем формат строк для этой области, чтобы сохранить исходную ширину колонок
        ОбластьДляВывода.СоздатьФорматСтрок();

        // Выводим обработанную область из временного документа в итоговый
        ИтоговыйТабДок.Вывести(ОбластьДляВывода);

        ИтоговыйТабДок.ВывестиГоризонтальныйРазделительСтраниц();
        ИтоговыйТабДок.ОтображатьСетку = Ложь;
    КонецЦикла;

    ИтоговыйТабДок.Показать();
КонецПроцедуры

Этот подход гарантирует, что даже при разных структурах печатных форм, колонки не будут "разъезжаться", и каждая форма будет выглядеть так, как она была задумана.

Рекомендации по использованию внешних печатных форм

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

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

Как использовать внешние печатные формы для объединения?

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

Пример структуры внешней печатной формы:


// В модуле объекта внешней обработки
Функция Печать(МассивОбъектов) Экспорт
    // Здесь МассивОбъектов - это массив ссылок на документы,
    // для которых нужно сформировать печатную форму.
    // Если печатная форма формируется для одного документа,
    // можно передавать ссылку на один документ.

    ИтоговыйТабДок = Новый ТабличныйДокумент;

    Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
        ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
        // ... Логика формирования печатной формы для одного ДокументОбъект
        // Например, используем типовые макеты или свои макеты обработки
        // ТабДокЧасть = СформироватьПечатнуюФормуДляДокумента(ДокументОбъект);

        // Допустим, у нас есть внутренняя функция, которая делает всю работу
        ТабДокЧасть = СформироватьПечатнуюФормуДляОдногоДокумента(ДокументОбъект);

        ВременныйТабДок = Новый ТабличныйДокумент;
        ВременныйТабДок.Вывести(ТабДокЧасть);
        ОбластьДляВывода = ВременныйТабДок.Область(1, 1, ВременныйТабДок.ВысотаТаблицы, ВременныйТабДок.ШиринаТаблицы);
        ОбластьДляВывода.СоздатьФорматСтрок();

        ИтоговыйТабДок.Вывести(ОбластьДляВывода);
        ИтоговыйТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЦикла;

    ИтоговыйТабДок.Показать(); // Показываем итоговый документ
    Возврат ИтоговыйТабДок; // Или возвращаем, если показ происходит снаружи
КонецФункции

Функция СформироватьПечатнуюФормуДляОдногоДокумента(ДокументОбъект)
    // Эта функция содержит логику формирования ТабличногоДокумента для одного документа.
    // Например, она может использовать макеты обработки или типовые макеты документа.
    ТабДок = Новый ТабличныйДокумент;
    // ... заполнение ТабДок данными из ДокументОбъект
    Возврат ТабДок;
КонецФункции

В этом сценарии, ваша внешняя обработка сама может содержать логику для объединения нескольких форм, принимая массив документов. Если же вы используете несколько внешних печатных форм (каждая для своего типа документа), то ваш код для сбора документов будет выглядеть так:


// В модуле, который вызывает внешние печатные формы
Процедура СформироватьОбъединеннуюПечать()
    ИтоговыйТабДок = Новый ТабличныйДокумент;

    // Пример: вызов Печать() из внешней обработки 1
    ВнешняяОбработка1 = ВнешниеОбработки.ПолучитьОбъект("ПутьКВнешнейОбработке1.epf");
    Для Каждого Док1 Из МассивДокументовТипа1 Цикл
        // Здесь мы вызываем функцию Печать() из внешней обработки,
        // передавая ей ссылку на текущий документ
        ТД_Часть = ВнешняяОбработка1.Печать(Док1);
        // ... (логика вывода ТД_Часть в ИтоговыйТабДок с СоздатьФорматСтрок и разделителями)
        ИтоговыйТабДок.Вывести(ТД_Часть);
        ИтоговыйТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЦикла;

    // Пример: вызов Печать() из внешней обработки 2
    ВнешняяОбработка2 = ВнешниеОбработки.ПолучитьОбъект("ПутьКВнешнейОбработке2.epf");
    Для Каждого Док2 Из МассивДокументовТипа2 Цикл
        ТД_Часть = ВнешняяОбработка2.Печать(Док2);
        // ... (логика вывода ТД_Часть в ИтоговыйТабДок с СоздатьФорматСтрок и разделителями)
        ИтоговыйТабДок.Вывести(ТД_Часть);
        ИтоговыйТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЦикла;

    ИтоговыйТабДок.Показать();
КонецПроцедуры

Мы рекомендуем использовать внешние печатные формы, так как это значительно упрощает поддержку и развитие вашей системы.

Дополнительные полезные советы

  1. Единственный вызов Показать(): Всегда вызывайте метод Показать() только один раз для итогового объединенного табличного документа после того, как все части будут в него выведены. Это предотвращает появление множества окон и оптимизирует производительность.
  2. Разделители страниц: Метод ВывестиГоризонтальныйРазделительСтраниц() объекта ТабличныйДокумент является вашим лучшим другом для обеспечения корректного разделения печатных форм на отдельные страницы при печати.
  3. Тонкая настройка печати: Объект ТабличныйДокумент предоставляет такие полезные свойства, как ОбластьПечати (для ограничения области печати) и ПовторятьПриПечатиСтроки (для вывода повторяющихся заголовков на каждой странице). Мы можем использовать их для более точной настройки.
  4. Серверное и клиентское взаимодействие: Помните, что формирование табличного документа (заполнение его данными) обычно происходит на сервере, а его отображение (метод Показать()) — на клиенте. Убедитесь, что ваш код корректно обрабатывает это взаимодействие.
  5. Шаблоны в Excel: При разработке сложных печатных форм часто бывает удобно сначала создать макет в Microsoft Excel. После этого вы можете импортировать его в 1С как макет табличного документа и использовать для заполнения. Это может значительно упростить процесс создания визуально привлекательных форм.

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

← На главную