Как проверить, помещается ли область на страницу при печати из Word-макета в 1С?

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

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

В этой статье мы подробно разберем, как обойти это ограничение, используя возможности самого Microsoft Word и программные методы взаимодействия через COM-соединение.

Метод 1: Использование свойств абзаца в шаблоне Word

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

Рассмотрим по шагам, как заставить Word автоматически следить за целостностью блока:

  1. Откройте ваш Word-макет и выделите область (строки или таблицу), которую нельзя разрывать.
  2. Перейдите в настройки абзаца (Paragraph Settings).
  3. На вкладке "Положение на странице" (Line and Page Breaks) активируйте флаг "Не отрывать от следующего" (Keep with next). Это заставит текущий абзац всегда «приклеиваться» к следующему. Если следующий абзац переходит на новую страницу, то и текущий перейдет вместе с ним.
  4. Также полезно включить флаг "Не разрывать абзац" (Keep lines together). Это гарантирует, что внутри одного абзаца (например, одной строки с должностью и ФИО) не возникнет разрыва страницы.

Этот способ идеально подходит для небольших блоков подписей. Word сам рассчитает высоту и при необходимости перенесет весь блок на следующий лист.

Метод 2: Программная проверка через COM-объект (ActiveX)

Если логика требует более сложного поведения, нам придется обратиться к объектной модели Word, учитывая при этом возможную оптимизацию и ускорение печати в docx. Выясним причину, почему это работает: когда БСП формирует печатную форму, она создает COM-объект приложения MS Word. Мы можем использовать свойство Information объекта Selection или Range.

Рассмотрим пример кода, который позволяет определить вертикальную позицию курсора на странице. Мы используем константу wdVerticalPositionRelativeToPage (числовое значение 6), которая возвращает расстояние от верхнего края страницы в пунктах.


// Предположим, у нас есть объект Word-документа, полученный из БСП
ОбъектWord = ПечатнаяФорма.СведенияОПечатнойФорме.MSWord;
Курсор = ОбъектWord.Application.Selection;

// Получаем текущую вертикальную позицию (в пунктах)
ТекущаяПозиция = Курсор.Information(6); // 6 = wdVerticalPositionRelativeToPage

// Получаем параметры страницы
ВысотаСтраницы = ОбъектWord.PageSetup.PageHeight;
НижнееПоле = ОбъектWord.PageSetup.BottomMargin;

// Вычисляем доступное место
ДоступноМеста = ВысотаСтраницы - НижнееПоле - ТекущаяПозиция;

// Если предполагаемая высота нашей области (например, 100 пунктов) больше доступного места
Если ДоступноМеста < 100 Тогда
    // Вставляем разрыв страницы программно
    Курсор.InsertBreak(7); // 7 = wdPageBreak
КонецЕсли;

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

Метод 3: Сравнение количества страниц (фиктивная вставка)

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

Разберем алгоритм по шагам:

  1. Запоминаем текущее количество страниц в документе. Для этого используем метод ComputeStatistics.
  2. Выводим нужную область (например, список подписантов).
  3. Снова проверяем количество страниц.
  4. Если количество страниц увеличилось, значит, произошел разрыв.

Посмотрим на пример реализации:


// 2 - это константа wdStatisticPages
КоличествоСтраницДо = ДокументWord.ComputeStatistics(2);

// Вызываем стандартный механизм БСП для вывода области
УправлениеПечатьюБСП.ЗаполнитьОбласть(ДокументWord, "Подписи", ДанныеПодписей);

КоличествоСтраницПосле = ДокументWord.ComputeStatistics(2);

Если КоличествоСтраницПосле > КоличествоСтраницДо Тогда
    // Если нам нужно, чтобы блок был целиком на новой странице, 
    // нам пришлось бы вставить разрыв ПЕРЕД выводом области.
    // В БСП это можно сделать, вставив символ разрыва в данные или макет.
КонецЕсли;

Метод 4: Использование таблиц для листов ознакомления

Часто в сообщениях форумов упоминается проблема "Листа ознакомления". Если список сотрудников большой, он неизбежно займет несколько страниц. Чтобы не потерять связь листов с основным приказом, воспользуемся особенностью таблиц Word.

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

Проанализируем преимущество этого метода:

Метод 5: Когда стоит перейти на Табличный документ (TabDoc)

Выясним причину, по которой иногда стоит последовать совету из "Сообщения 7" и переделать макет на ТабДок.

В современных версиях БСП (3.0 и выше) активно внедряется серверная печать в формате PDF. Если на сервере 1С не установлен Microsoft Office, стоит рассмотреть шаблон ВПФ для вывода в Word без использования COM-соединения. В тех случаях, когда БСП использует внутренние библиотеки для рендеринга, COM-объект MS Word не создается, и все методы типа ComputeStatistics или Information перестают работать.

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


МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьПодписи);

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

ТабДок.Вывести(ОбластьПодписи);

Резюме

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

← На главную