При разработке внешних печатных форм с использованием Библиотеки стандартных подсистем (БСП) программисты часто сталкиваются с ситуацией, когда при попытке вывода на печать возникает исключение: «В обработчике печати не был сформирован табличный документ для: [ИмяКоманды]». Ситуация становится особенно запутанной, когда мы планируем выводить не табличный документ (MXL), а офисный документ в формате Microsoft Word (DOCX). Разберем по шагам, почему возникает эта ошибка, как работает механизм сопоставления идентификаторов и как правильно инициализировать структуру офисного документа в коде 1С.
Проанализируем механизм работы БСП. Когда пользователь нажимает кнопку печати, система обращается к модулю внешней обработки и вызывает экспортную процедуру Печать. В эту процедуру передается параметр КоллекцияПечатныхФорм, который является таблицей значений. БСП ожидает, что после завершения работы процедуры в этой таблице для каждой запрошенной команды будут заполнены данные: либо в колонке ТабличныйДокумент, либо в колонке ОфисныеДокументы.
Рассмотрим код регистрации нашей обработки. В функции СведенияОВнешнейОбработке мы указываем идентификатор команды:
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = НСтр("ru = 'Приказ'");
НоваяКоманда.Идентификатор = "ПриказВПФ";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода;
Теперь посмотрим на условие в процедуре Печать из сообщения автора:
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПФ_MXL_ПриказОВнесенииИзмененийШтатноеРасписание") Тогда
СформироватьДокументWord(КоллекцияПечатныхФорм, МассивОбъектов);
КонецЕсли;
Проблема очевидна: в регистрации указан идентификатор ПриказВПФ, а проверка и дальнейшее заполнение коллекции происходит по идентификатору ПФ_MXL_ПриказОВнесенииИзмененийШтатноеРасписание. В результате метод УправлениеПечатью.НужноПечататьМакет возвращает Ложь, формирование документа не запускается, и БСП видит пустую коллекцию для команды ПриказВПФ.
Рассмотрим два способа приведения кода в порядок. Мы рекомендуем использовать первый вариант, так как он делает код более прозрачным.
Вариант 1: Синхронизация идентификатора с именем макета. В функции регистрации измените идентификатор на имя вашего макета:
НоваяКоманда.Идентификатор = "ПФ_MXL_ПриказОВнесенииИзмененийШтатноеРасписание";
Вариант 2: Использование программного идентификатора. Оставьте идентификатор коротким, но используйте именно его во всех проверках процедуры Печать:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ПриказВПФ") Тогда
СформироватьДокументWord(КоллекцияПечатныхФорм, МассивОбъектов, "ПриказВПФ");
КонецЕсли;
КонецПроцедуры
Многих сбивает с толку текст ошибки: «В обработчике печати не был сформирован табличный документ». Проанализируем ситуацию: это стандартное сообщение БСП. Логика проверки внутри общего модуля УправлениеПечатью устроена так: система проверяет поле ТабличныйДокумент. Если оно пустое, проверяется поле ОфисныеДокументы. Если и там пусто (из-за того, что мы обратились к коллекции по неверному ключу), выбрасывается исключение по умолчанию, в котором упоминается табличный документ как наиболее распространенный тип печатной формы.
Посмотрим, как должна выглядеть процедура формирования документа, чтобы избежать ошибок инициализации. Важно правильно использовать методы БСП для работы с офисными макетами. Рассмотрим пошагово:
УправлениеПечатью.СведенияОПечатнойФорме. Он возвращает структуру, которая является ссылкой на строку в коллекции.ОфисныеДокументы.Посмотрим на пример правильной реализации заполнения структуры:
// Получаем структуру печатной формы из коллекции по верному Идентификатору
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ПриказВПФ");
// Инициализируем макет (ТипМакета может быть "DOC" или "DOCX")
ДвоичныеДанныеМакета = ПолучитьМакет("ПФ_MXL_ПриказОВнесенииИзмененийШтатноеРасписание");
СсылкаНаМакет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, "DOCX", "Приказ");
// Инициализируем саму печатную форму
ПечатнаяФормаWord = УправлениеПечатью.ИнициализироватьПечатнуюФорму("DOCX", СсылкаНаМакет.НастройкиСтраницыМакета, СсылкаНаМакет);
// ... здесь логика заполнения параметров через ПрисоединитьОбластьИЗаполнитьПараметры ...
// Финализируем документ и получаем адрес во временном хранилище
АдресХранилища = УправлениеПечатью.СформироватьДокумент(ПечатнаяФормаWord);
// Важно: создаем соответствие для офисных документов
ОфисныеДокументы = Новый Соответствие;
ОфисныеДокументы.Вставить(АдресХранилища, "Приказ_о_внесении_изменений.docx");
// Заполняем свойство в структуре ПечатнаяФорма
ПечатнаяФорма.ОфисныеДокументы = ОфисныеДокументы;
Проанализируем технические нюансы форматов. В старых версиях БСП часто использовался тип DOC. Однако его использование требует наличия установленного Microsoft Word на сервере 1С, так как формирование происходит через COM-объект. Это порождает ряд проблем: низкую производительность, утечки памяти процесса WINWORD.EXE и ошибки прав доступа под пользователем usr1cv8.
Рекомендация: Всегда используйте формат DOCX. Современная БСП умеет работать с DOCX как с набором XML-файлов без использования COM-соединения. Это работает значительно стабильнее и быстрее, не требуя стороннего ПО на серверной стороне. Для ускорения разработки можно взять готовый шаблон внешней печатной формы для вывода в Word средствами БСП.
Не забывайте об очистке ресурсов. При формировании офисных документов создаются временные файлы в профиле пользователя на сервере. Чтобы не допустить переполнения диска, обязательно вызывайте методы очистки ссылок:
УправлениеПечатью.ОчиститьСсылки(ПечатнаяФормаWord, Ложь);
УправлениеПечатью.ОчиститьСсылки(СсылкаНаМакет);
Обратите внимание на второй параметр метода ОчиститьСсылки. Значение Ложь означает, что мы не удаляем временное хранилище сразу, так как оно понадобится платформе для передачи файла клиенту.
Часто ошибка «документ не сформирован» может быть следствием того, что запрос к данным вернул пустой результат, и код просто «проскочил» заполнение коллекции. Рассмотрим пример получения данных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ИзменениеШтатногоРасписания.Номер КАК Номер,
| ИзменениеШтатногоРасписания.Дата КАК Дата
|ИЗ
| Документ.ИзменениеШтатногоРасписания КАК ИзменениеШтатногоРасписания
|ГДЕ
| ИзменениеШтатногоРасписания.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Возврат; // Если данных нет, коллекция останется пустой и возникнет ошибка БСП
КонецЕсли;
Чтобы избежать неинформативного сообщения БСП, рекомендуется добавлять проверку на наличие данных в самом начале процедуры печати и выводить пользователю понятное предупреждение через ОбщегоНазначенияКлиентСервер.СообщитьПользователю, если объект не готов к печати.
Таким образом, для успешного формирования печатной формы Word необходимо строго соблюдать соответствие идентификаторов в трех местах: функции СведенияОВнешнейОбработке, проверке НужноПечататьМакет и при получении структуры СведенияОПечатнойФорме. Правильное использование типа DOCX и своевременная очистка ссылок обеспечат стабильную работу вашей внешней печатной формы. Для быстрого поиска нужных процедур и функций подсистемы печати пригодится справочник по методам БСП с примерами использования.