Как правильно настроить и заполнить внешние печатные формы Word в 1С:ЗУП 3.1 с использованием БСП?

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

При работе с системой 1С:Зарплата и управление персоналом (ЗУП) версии 3.1 и выше, часто возникает потребность в создании внешних печатных форм, особенно для офисных документов, таких как Word. Это позволяет гибко настраивать вывод данных в соответствии с уникальными требованиями предприятия, используя уже подготовленные шаблоны Word. Однако, процесс разработки таких форм может вызвать ряд вопросов и проблем, связанных с правильной регистрацией, получением данных и, самое главное, корректным заполнением параметров в Word-шаблоне.

В данной статье мы подробно рассмотрим, как создать внешнюю печатную форму в формате Word для документа "Прием на работу" в 1С:ЗУП, используя механизмы Библиотеки стандартных подсистем (БСП). Мы разберем типовые ошибки, такие как незаполнение параметров или некорректная обработка табличных документов, и предложим рабочее решение.

1. Понимание различий между табличными документами и офисными формами Word

Одной из первых ошибок, с которой можно столкнуться при разработке внешних печатных форм для Word, является попытка использовать объект ТабличныйДокумент. Изначально, для вывода печатных форм в 1С активно использовался именно ТабличныйДокумент, который является встроенным инструментом для создания печатных макетов в формате таблиц 1С.

Рассмотрим пример кода, который часто используется по инерции, но является избыточным или даже ошибочным для Word-документов:

ПечатнаяФорма.ТабличныйДокумент = Новый ТабличныйДокумент;

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

2. Регистрация внешней печатной формы Word в 1С:ЗУП

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

Обратим внимание на ключевые моменты при регистрации для офисных документов:

  1. Вид обработки: Указываем, что это печатная форма, предназначенная для офисных документов. Для этого используем ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма().

  2. Назначение: Определяем, для каких документов или справочников будет доступна данная печатная форма. В нашем случае это документы "ПриемНаРаботу", "ПриемНаРаботуСписком" и справочник "Сотрудники".

  3. Команда: Задаем команду, которая будет отображаться в меню "Печать". Важно указать Использование команды как ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(), так как вся логика формирования Word-документа выполняется на сервере.

Пример кода функции СведенияОВнешнейОбработке():


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

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

Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "")
    НоваяКоманда = ТаблицаКоманд.Добавить();
    НоваяКоманда.Представление         = Представление; 
    НоваяКоманда.Идентификатор         = Идентификатор;
    НоваяКоманда.Использование         = Использование;
    НоваяКоманда.ПоказыватьОповещение     = ПоказыватьОповещение;
    НоваяКоманда.Модификатор         = Модификатор;
КонецПроцедуры

Процедура Печать() является точкой входа для команды печати. В ней мы вызываем нашу основную функцию для формирования документа.


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    ПечатьДокумента(КоллекцияПечатныхФорм, МассивОбъектов, ОбъектыПечати);
КонецПроцедуры 

3. Получение данных для печати

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


Процедура ПечатьДокумента(КоллекцияПечатныхФорм, МассивОбъектов, ОбъектыПечати)
    МассивДанныхЗаполнения = ПолучитьДанныеДляПечатиДокумента(МассивОбъектов);     
    СформироватьПечатнуюФорму(КоллекцияПечатныхФорм, МассивДанныхЗаполнения, ОбъектыПечати);
КонецПроцедуры

Функция ПолучитьДанныеДляПечатиДокумента(МассивОбъектов)
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    |    ПриемНаРаботу.Дата КАК Дата,
    |    ПриемНаРаботу.Номер КАК Номер,
    |    ПриемНаРаботу.Организация КАК Организация,
    |    ПриемНаРаботу.Подразделение КАК Подразделение,
    |    ПриемНаРаботу.Сотрудник КАК Сотрудник,
    |    ПриемНаРаботу.Должность КАК Должность,
    |    ПриемНаРаботу.ДатаПриема КАК ДатаПриема,
    |    ПриемНаРаботу.УсловияПриема КАК УсловияПриема,
    |    ПриемНаРаботу.Руководитель КАК Руководитель,
    |    ПриемНаРаботу.ДолжностьРуководителя КАК ДолжностьРуководителя,
    |    ПриемНаРаботу.ДлительностьИспытательногоСрока КАК ДлительностьИспытательногоСрока,
    |    ПриемНаРаботу.ТрудовойДоговорНомер КАК ТрудовойДоговорНомер,
    |    ПриемНаРаботу.ТрудовойДоговорДата КАК ТрудовойДоговорДата
    |ИЗ
    |    Документ.ПриемНаРаботу КАК ПриемНаРаботу
    |ГДЕ
    |    ПриемНаРаботу.Ссылка = &Ссылка";
    Запрос.УстановитьПараметр("Ссылка", МассивОбъектов[0]);
    Возврат Запрос.Выполнить().Выгрузить();
КонецФункции

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

4. Подготовка шаблона Word и его загрузка в 1С

Для создания шаблона Word мы используем специальные теги в фигурных скобках {v8 ...}. Существует два основных типа тегов:

  1. Области: {v8 Область.ИмяОбласти} и {/v8 Область.ИмяОбласти}. Эти парные теги определяют начало и конец именованной области макета в Word-документе. Они не выводятся на печать и служат для программного выделения блоков текста, которые могут повторяться или заполняться особым образом.

  2. Параметры: {v8 ИмяПараметра}. Это обычные параметры, которые будут заменены значениями из 1С. Они сохраняют форматирование (шрифт, цвет, фон) и не требуют закрывающего тега.

Например, если нам нужно вывести дату трудового договора, в шаблоне Word мы можем разместить текст: "Дата договора: {v8 ДатаДоговора}".

После создания шаблона Word (например, в формате DOCX), его необходимо загрузить в 1С в виде двоичных данных. Обычно это делается через объект "Макеты" в конфигурации или непосредственно через внешнюю обработку, где макет хранится как двоичные данные. Рекомендуется называть макеты по аналогии с БСП, например, ПФ_DOC_ТрудовойДоговор.

5. Инициализация Word-макета и печатной формы в 1С

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


Процедура СформироватьПечатнуюФорму(КоллекцияПечатныхФорм, МассивДанныхЗаполнения, ОбъектыПечати)
    ДвоичныеДанныеМакета = ПолучитьМакет("ПФ_DOC_ТрудовойДоговор");
    
    Если ДвоичныеДанныеМакета <> Неопределено Тогда
        // Создаем объект сведений о печатной форме для ее добавления в коллекцию
        ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ПечатьТрудовогоДоговора");
        
        // ВАЖНО: для Word-документов эта строка, по идее, не нужна,
        // но иногда ее оставляют для обхода проверок, если система ожидает ТабличныйДокумент.
        // Корректнее использовать ПечатнаяФорма.ОфисныеДокументы.
        ПечатнаяФорма.ТабличныйДокумент = Новый ТабличныйДокумент;
        
        // Инициализируем макет офисного документа из двоичных данных
        // Тип документа (например, "docx") можно передать вторым параметром, если необходимо.
        Макет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, Неопределено);
        
        Если Макет = Неопределено Тогда
            Сообщить("Не удалось инициализировать макет офисного документа.");
            Возврат;
        КонецЕсли;
        
        // Инициализируем объект печатной формы, куда будем присоединять области и параметры
        ПечатнаяФормаДокумента = УправлениеПечатью.ИнициализироватьПечатнуюФорму(Неопределено, Макет.НастройкиСтраницыМакета, Макет);        
        
        Если ПечатнаяФормаДокумента = Неопределено Тогда
            Сообщить("Не удалось инициализировать печатную форму документа.");
            УправлениеПечатью.ОчиститьСсылки(Макет);
            Возврат;
        КонецЕсли;
        
        // ... (далее будет код по заполнению параметров)
        
    КонецЕсли;
КонецПроцедуры

Мы используем УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента() для подготовки макета и УправлениеПечатью.ИнициализироватьПечатнуюФорму() для создания объекта, в который мы будем "собирать" наш Word-документ.

6. Основная проблема: Корректное заполнение параметров Word-шаблона

Одна из наиболее частых проблем, с которой сталкиваются разработчики, — это незаполнение параметров в Word-документе. Корень проблемы часто кроется в неправильной передаче данных в функцию УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры().

Функция ПрисоединитьОбластьИЗаполнитьПараметры ожидает в качестве третьего параметра либо скалярное значение (если область сама по себе является простым параметром), либо структуру (или соответствие), ключи которой соответствуют именам параметров, указанных в Word-шаблоне (например, {v8 ИмяПараметра}).

Рассмотрим проблемный участок кода из исходного сообщения:


Область = Новый Структура;
Область.Вставить("ИмяОбласти", "ДатаДоговора");
Область.Вставить("ТипОбласти", "Общая");

Область = УправлениеПечатью.ОбластьМакета(Макет, Область);
// Некорректная передача данных: передается только значение
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения[0].ТрудовойДоговорДата);

Здесь мы пытаемся присоединить область с именем "ДатаДоговора" и передать в нее одно значение (дату). Если в Word-шаблоне внутри этой области есть параметр, например, {v8 ДатаДоговора}, то простое значение не будет автоматически сопоставлено с этим параметром.

Правильный подход:

Необходимо передавать Структуру, где ключ — это имя параметра из Word-шаблона, а значение — это данные для заполнения. Также важно убедиться, что область в Word-шаблоне корректно определена. Если мы хотим заполнить отдельный параметр, не обязательно определять его как "область" в смысле {v8 Область.ИмяОбласти}. Достаточно простого параметра {v8 ИмяПараметра} в любом месте документа.

Давайте изменим процедуру СформироватьПечатнуюФорму для корректного заполнения параметров. Предположим, что в нашем Word-шаблоне есть параметр с именем ДатаДоговора (т.е. {v8 ДатаДоговора}) и, возможно, другие параметры типа НомерДоговора и т.д.


// Продолжение Процедуры СформироватьПечатнуюФорму

        // Получаем данные для текущего объекта (документа ПриемНаРаботу)
        ДанныеОбъекта = МассивДанныхЗаполнения[0]; // МассивДанныхЗаполнения - это ТаблицаЗначений, берем первую строку
        
        // Создаем структуру для передачи параметров
        ПараметрыДляЗаполнения = Новый Структура;
        
        // Заполняем структуру данными из нашей ТаблицыЗначений
        // Имена полей структуры должны совпадать с именами параметров в Word-шаблоне ({v8 ИмяПараметра})
        ПараметрыДляЗаполнения.Вставить("ДатаДоговора", ДанныеОбъекта.ТрудовойДоговорДата);
        ПараметрыДляЗаполнения.Вставить("НомерДоговора", ДанныеОбъекта.ТрудовойДоговорНомер);
        ПараметрыДляЗаполнения.Вставить("ДатаПриема", ДанныеОбъекта.ДатаПриема);
        ПараметрыДляЗаполнения.Вставить("ФИОСотрудника", ДанныеОбъекта.Сотрудник.Наименование); // Пример: если Сотрудник - ссылка
        ПараметрыДляЗаполнения.Вставить("НаименованиеОрганизации", ДанныеОбъекта.Организация.Наименование); // Если Организация - ссылка
        // Добавляем другие необходимые параметры...
        
        // Пример работы с общей областью, если она нужна (например, для шапки документа)
        // Если в Word-шаблоне есть область {v8 Область.Заголовок} ... {/v8 Область.Заголовок}
        // и внутри нее есть параметры, то мы можем передать их все одной структурой.
        ОбластьЗаголовок = Новый Структура;
        ОбластьЗаголовок.Вставить("ИмяОбласти", "Заголовок");
        ОбластьЗаголовок.Вставить("ТипОбласти", "Общая");
        
        Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьЗаголовок);
        
        Если Область <> Неопределено Тогда
            // Теперь передаем ВСЮ структуру с параметрами
            УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, ПараметрыДляЗаполнения, Ложь);
        Иначе
            Сообщить("Область 'Заголовок' не найдена в макете.");
            // Если нет областей, но есть параметры в документе, их можно заполнить другим способом,
            // либо убедиться, что весь документ рассматривается как одна область для заполнения.
            // Для одиночных параметров, расположенных вне именованных областей,
            // можно использовать другой подход или просто убедиться, что ПрисоединитьОбластьИЗаполнитьПараметры
            // вызывается для всего документа.
        КонецЕсли;

        // Если вы хотите заполнить параметры, которые находятся вне именованных областей,
        // вы можете вызвать ПрисоединитьОбластьИЗаполнитьПараметры для всего документа
        // или использовать макет как основную область. В большинстве случаев
        // передача структуры с параметрами в единственном вызове для главной области (или для всего документа)
        // будет достаточной.
        // Пример для заполнения всех параметров без явных областей:
        // УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Макет, ПараметрыДляЗаполнения, Ложь);
        // Однако чаще всего используется модель с областями.
        
        // ... (далее код по формированию документа)
КонецПроцедуры

В приведенном примере мы сначала получаем данные из МассивДанныхЗаполнения[0] (строка ТаблицыЗначений). Затем создаем новую Структуру ПараметрыДляЗаполнения и наполняем ее ключами, которые точно соответствуют именам параметров в Word-шаблоне (например, ДатаДоговора). После этого мы передаем эту Структуру в УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(). Это гарантирует, что функция сможет корректно сопоставить данные с параметрами в Word-документе.

7. Формирование и вывод Word-документа

После того как все области присоединены и параметры заполнены, мы формируем окончательный Word-документ и помещаем его во временное хранилище. Затем связываем его с объектом ПечатнаяФорма для вывода на экран или печати.


// Продолжение Процедуры СформироватьПечатнуюФорму

        АдресХранилищаОфисныйДокумент = УправлениеПечатью.СформироватьДокумент(ПечатнаяФормаДокумента);
        
        // Очищаем ссылки на объекты после использования для освобождения памяти
        УправлениеПечатью.ОчиститьСсылки(ПечатнаяФормаДокумента, Ложь);
        УправлениеПечатью.ОчиститьСсылки(Макет);
        
        // Создаем соответствие для хранения офисных документов
        ОфисныеДокументы = Новый Соответствие;
        ОфисныеДокументы.Вставить(АдресХранилищаОфисныйДокумент, НСтр("ru = 'Трудовой договор'")); // Название документа в списке
        
        // Присваиваем сформированный офисный документ объекту печатной формы
        ПечатнаяФорма.СинонимМакета    = НСтр("ru = 'Трудовой договор (документ Microsoft Word)'");
        ПечатнаяФорма.ОфисныеДокументы = ОфисныеДокументы;
        
    КонецЕсли; // Если ДвоичныеДанныеМакета <> Неопределено
КонецПроцедуры

Метод УправлениеПечатью.СформироватьДокумент() создает итоговый Word-файл и возвращает адрес, по которому он доступен во временном хранилище. Этот адрес затем используется в ПечатнаяФорма.ОфисныеДокументы. УправлениеПечатью.ОчиститьСсылки() важен для управления памятью, особенно при серверных вызовах.

8. Отладка внешних печатных форм

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

  1. Использование специальных обработок-отладчиков: На различных ресурсах (например, Infostart) можно найти обработки, предназначенные специально для отладки внешних печатных форм. Они позволяют "подключать" вашу внешнюю обработку и ставить в ней точки останова.

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

  3. "Лайфхак" отладки: Можно вручную создать объект внешней обработки в коде (например, во временной процедуре в конфигурации), указав полное имя файла обработки и установив БезопасныйРежим = Ложь. Это позволит на лету править код обработки и отлаживать его.

Во время отладки обращайте особое внимание на структуру данных, передаваемых в ПрисоединитьОбластьИЗаполнитьПараметры, и на то, как функция УправлениеПечатью.ОбластьМакета возвращает информацию об областях.

9. Дополнительные возможности и распространенные ошибки

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

  2. Работа с закладками Word: В качестве альтернативы заполнению параметров можно использовать закладки Word. Это может быть удобнее для вставки больших объемов текста, поскольку длина строки, передаваемой через закладки, как правило, не ограничена и не требует определения отдельных областей для каждого параметра.

  3. Проблемы с областями: Если в Word-шаблоне используются области, они должны быть корректно определены (открывающий и закрывающий теги для именованных областей) и не могут быть пустыми. Если область пуста, БСП может ее не вывести или некорректно обработать.

  4. Использование ОбщегоНазначения.СообщитьПользователю(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));: Всегда оборачивайте код формирования в блок Попытка...Исключение, чтобы отлавливать ошибки и сообщать их пользователю, особенно при работе с внешними COM-объектами Word, которые могут быть чувствительны к правам доступа или некорректному формату данных.

В заключение, создание внешних печатных форм Word в 1С:ЗУП — это мощный инструмент для кастомизации документов. Главное — внимательно следовать рекомендациям БСП, особенно в части подготовки Word-шаблонов и корректной передачи данных в функции заполнения параметров. Понимание того, что ПрисоединитьОбластьИЗаполнитьПараметры ожидает структуру с именами параметров, является ключевым для успешного решения проблемы незаполнения.

← На главную