При разработке и кастомизации печатных форм в системе 1С:Предприятие 7.7 программисты часто сталкиваются с нестандартными бизнес-требованиями. Одно из них — необходимость разбить одну крупную сумму в документе на несколько более мелких печатных форм прямо в процессе вывода на печать. При этом документы должны нумероваться по порядку (например, "№ 123/1", "№ 123/2" и так далее), но физически плодить новые документы в базе данных не требуется.
Естественным решением такой задачи является использование цикла. Однако здесь возникает серьезное техническое препятствие: как «обнулить» содержимое объекта таблицы после очередной итерации цикла, чтобы не создавать множество переменных под каждый отдельный документ? Рассмотрим этот вопрос подробно и разберем все доступные варианты реализации.
В более современных версиях платформы (1С:Предприятие 8.х) для управления выводом на печать используется объект ТабличныйДокумент, у которого есть встроенный метод Очистить(). В платформе 1С 7.7 встроенный объект Таблица устроен иначе. У него нет метода для очистки содержимого.
Выясним причину этой особенности. В 1С 7.7 объект Таблица тесно связан с шаблоном (макетом) и контекстом выполнения. Если мы просто попытаемся очистить ячейки, платформа потеряет связь со структурой исходного макета. Единственным надежным способом «обнулить» таблицу под тем же именем переменной является её повторная инициализация с помощью конструктора СоздатьОбъект("Таблица").
Ниже мы подробно разберем по шагам три основных сценария реализации печати измененных документов в цикле.
Этот способ отлично подходит, если документов немного (до 5 штук) и пользователю необходимо визуально проверить каждый из них перед отправкой на принтер.
Секрет этого метода кроется в особенностях жизненного цикла окон в 1С 7.7. Когда мы вызываем метод Показать(), управление окном передается операционной системе Windows. Последующее пересоздание переменной Таб в цикле кода 1С не закрывает уже открытое на экране окно.
Рассмотрим пример реализации этого сценария на встроенном языке:
// Предположим, у нас есть ИсходнаяСумма и НомерДокумента
КолДокументов = 3; // Количество частей, на которые делим сумму
ИсходныйНомер = НомерДок;
Для Ном = 1 По КолДокументов Цикл
// Шаг 1: Каждый раз создаем объект заново, очищая переменную
Таб = СоздатьОбъект("Таблица");
// Шаг 2: Обязательно загружаем макет заново
Таб.ИсходнаяТаблица("ТаблицаДокумента");
// Шаг 3: Рассчитываем параметры для вывода в макет
НомерВывода = ИсходныйНомер + "/" + Ном;
СуммаВывода = ИсходнаяСумма / КолДокументов;
// Переменные "НомерВывода" и "СуммаВывода" должны быть прописаны в ячейках макета
Таб.ВывестиСекцию("Шапка");
Таб.ВывестиСекцию("Строка");
Таб.ВывестиСекцию("Подвал");
// Шаг 4: Отображаем документ в отдельном окне
Таб.Показать("Печатная форма часть " + Ном, "");
КонецЦикла;
Важный нюанс: Не используйте этот метод, если документов в цикле будет много (например, более 10). Открытие десятков окон одновременно может привести к перегрузке графического интерфейса 1С и оперативной памяти компьютера пользователя.
Проанализируем более профессиональный и элегантный подход. Вместо того чтобы заставлять пользователя метаться между множеством открытых окон на экране, мы можем сформировать все измененные документы внутри одного общего объекта Таблица. На стыке документов мы будем использовать принудительный разрыв страницы.
В этом случае нам вообще не нужно пересоздавать и обнулять объект Таблица внутри цикла. Мы инициализируем его один раз перед началом цикла. Посмотрим на пример кода:
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("ТаблицаДокумента"); // Загружаем макет один раз
КолДокументов = 3;
ИсходныйНомер = НомерДок;
Для Ном = 1 По КолДокументов Цикл
// Обновляем значения переменных для каждой итерации
НомерВывода = ИсходныйНомер + "/" + Ном;
СуммаВывода = ИсходнаяСумма / КолДокументов;
// Выводим секции текущего документа
Таб.ВывестиСекцию("Шапка");
Таб.ВывестиСекцию("Строка");
Таб.ВывестиСекцию("Подвал");
// Если это не последний документ в цикле, добавляем разделитель страниц
Если Ном < КолДокументов Тогда
Таб.НоваяСтраница();
КонецЕсли;
КонецЦикла;
// Настраиваем параметры отображения результирующего документа
Таб.Опции(0, 0, 0, 0); // Отключаем сетку и заголовки строк/колонок
Таб.ТолькоПросмотр(1); // Защищаем документ от случайного редактирования
Таб.Показать("Печать разбитых документов", "");
Этот способ имеет неоспоримые преимущества. Во-первых, экономится оперативная память. Во-вторых, пользователь видит один структурированный документ и может отправить все разбитые формы на принтер всего одним нажатием кнопки «Печать».
Рассмотрим ситуацию, когда пользователю вообще не нужно видеть печатные формы на экране компьютера. Документы должны сразу отправляться на принтер.
В этом случае мы комбинируем пересоздание объекта таблицы и метод непосредственной отправки в очередь печати Напечатать():
КолДокументов = 3;
ИсходныйНомер = НомерДок;
Для Ном = 1 По КолДокументов Цикл
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("ТаблицаДокумента");
НомерВывода = ИсходныйНомер + "/" + Ном;
СуммаВывода = ИсходнаяСумма / КолДокументов;
Таб.ВывестиСекцию("Шапка");
Таб.ВывестиСекцию("Строка");
Таб.ВывестиСекцию("Подвал");
// Настраиваем параметры страницы (например, масштаб по ширине листа)
Таб.ПараметрыСтраницы(1,,,,,,,1,,);
// Параметр 0 означает печать без вывода стандартного диалогового окна Windows
Таб.Напечатать(0);
КонецЦикла;
Предупреждение при пакетной печати: При отправке большого количества документов напрямую на принтер в быстром цикле служба печати операционной системы (Spooler) или сетевой драйвер принтера могут захлебнуться потоком задач. В результате некоторые документы могут не напечататься.
Если вы столкнулись с потерей документов при пакетной печати, рекомендуется использовать один из двух обходных путей:
Напечатать(0) (например, через запуск внешней компоненты или вызов функции предупреждения с таймаутом).Мы проанализировали особенности работы с печатными формами в 1С:Предприятии 7.7. Несмотря на отсутствие встроенного метода очистки табличного документа, задача циклической печати измененных форм решается очень просто. Вы можете либо пересоздавать объект внутри цикла через СоздатьОбъект("Таблица"), либо объединять все документы в одну большую таблицу с разрывами страниц при помощи метода НоваяСтраница(). Выбирайте вариант, наиболее подходящий под ваши бизнес-процессы.