При формировании кадровых и произвольных печатных форм в формате Microsoft Word часто требуется подставить паспортные данные сотрудников: серию, номер, дату выдачи и кем выдан документ. В конфигурациях 1С (например, «1С:Зарплата и Управление Персоналом») паспортные данные привязаны к физическому лицу и хранятся в периодическом регистре сведений ПаспортныеДанныеФизЛиц.
Разберем по шагам, как правильно составить запрос к регистру сведений срез последних, связать данные документа с физическим лицом и заполнить шаблон документа Word через COM-соединение.
Сотрудник документа ссылается на справочник физических лиц, по которому и ведется учет документов, удостоверяющих личность. Для оптимального быстродействия сначала выберем состав сотрудников во временную таблицу, а затем выполним левое соединение с виртуальной таблицей СрезПоследних регистра сведений.
Рассмотрим пример правильного текста запроса:
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
// Передаем дату документа для получения паспорта, актуального на момент оформления
Запрос.УстановитьПараметр("Период", ?(ЗначениеЗаполнено(СсылкаНаОбъект.Дата), СсылкаНаОбъект.Дата, ТекущаяДата()));
Запрос.Текст =
"ВЫБРАТЬ
| Работники.Сотрудник КАК Сотрудник,
| Работники.ФизЛицо КАК ФизЛицо
|ПОМЕСТИТЬ втРаботники
|ИЗ
| Документ.ПриемНаРаботуВОрганизацию.РаботникиОрганизации КАК Работники
|ГДЕ
| Работники.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| Работники.Сотрудник,
| Работники.ФизЛицо
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| втРаботники.Сотрудник КАК Сотрудник,
| Паспорта.ДокументВид КАК ВидДокумента,
| Паспорта.ДокументСерия КАК Серия,
| Паспорта.ДокументНомер КАК Номер,
| Паспорта.ДокументДатаВыдачи КАК ДатаВыдачи,
| Паспорта.ДокументКемВыдан КАК КемВыдан,
| Паспорта.ДокументКодПодразделения КАК КодПодразделения,
| Паспорта.ДатаРегистрацииПоМестуЖительства КАК АдресРегистрации
|ИЗ
| втРаботники КАК втРаботники
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПаспортныеДанныеФизЛиц.СрезПоследних(&Период, ) КАК Паспорта
| ПО втРаботники.ФизЛицо = Паспорта.ФизЛицо
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ втРаботники";
Конструкция УНИЧТОЖИТЬ втРаботники освобождает оперативную память сервера СУБД после выполнения запроса и не удаляет сами данные сотрудников из информационной базы.
Выясним причину популярной ошибки, возникающей при попытке объединить запрос в единую выборку с группировкой по полям паспорта:
В типовых конфигурациях реквизит ДокументКемВыдан имеет строковый тип неограниченной длины. Язык запросов 1С не позволяет использовать поля неограниченной длины в секциях СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, а также в агрегатных функциях МАКСИМУМ() и МИНИМУМ() без явного ограничения длины.
Если вам необходимо сгруппировать данные или использовать агрегатные функции в одном запросе, обязательно примените функцию ВЫРАЗИТЬ:
ВЫРАЗИТЬ(Паспорта.ДокументКемВыдан КАК Строка(500)) КАК КемВыдан
Проанализируем процедуру формирования печатной формы. Макет Word хранится в двоичных данных или ActiveDocument макета обработки. Для замены текстовых меток (тегов) используется объектная модель Word.Application.
Посмотрим на готовый программный код функции печати:
Функция Печать() Экспорт
// Получаем макет документа Word
МакетОбъект = ПолучитьМакет("Макет");
ОбъектВорд = МакетОбъект.Получить();
Документ = ОбъектВорд.Application.Documents(1);
Документ.Activate();
// Выполняем выборку паспортных данных
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
Запрос.УстановитьПараметр("Период", ?(ЗначениеЗаполнено(СсылкаНаОбъект.Дата), СсылкаНаОбъект.Дата, ТекущаяДата()));
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Работники.Сотрудник КАК Сотрудник,
| Работники.ФизЛицо КАК ФизЛицо,
| Паспорта.ДокументВид КАК ВидДокумента,
| Паспорта.ДокументСерия КАК Серия,
| Паспорта.ДокументНомер КАК Номер,
| Паспорта.ДокументДатаВыдачи КАК ДатаВыдачи,
| ВЫРАЗИТЬ(Паспорта.ДокументКемВыдан КАК Строка(500)) КАК КемВыдан,
| Паспорта.ДокументКодПодразделения КАК КодПодразделения
|ИЗ
| Документ.ПриемНаРаботуВОрганизацию.РаботникиОрганизации КАК Работники
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПаспортныеДанныеФизЛиц.СрезПоследних(&Период, ) КАК Паспорта
| ПО Работники.ФизЛицо = Паспорта.ФизЛицо
|ГДЕ
| Работники.Ссылка = &Ссылка";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Замена = Документ.Content.Find;
// Подстановка ФИО сотрудника
Замена.Execute("[Сотрудник]", Ложь, Истина, Ложь, , , Истина, , Ложь, Строка(Выборка.Сотрудник), 2);
// Подстановка серии и номера паспорта
ПаспортСерияНомер = "серия " + СокрЛП(Выборка.Серия) + " № " + СокрЛП(Выборка.Номер);
Замена.Execute("[ПаспортСерияНомер]", Ложь, Истина, Ложь, , , Истина, , Ложь, ПаспортСерияНомер, 2);
// Подстановка даты выдачи с обработкой пустых значений
СтрДатаВыдачи = Формат(Выборка.ДатаВыдачи, "ДФ=dd.MM.yyyy; ДП=''");
Замена.Execute("[ДатаВыдачи]", Ложь, Истина, Ложь, , , Истина, , Ложь, СтрДатаВыдачи, 2);
// Подстановка органа, выдавшего документ
Замена.Execute("[КемВыдан]", Ложь, Истина, Ложь, , , Истина, , Ложь, СокрЛП(Выборка.КемВыдан), 2);
// Подстановка кода подразделения
Замена.Execute("[КодПодразделения]", Ложь, Истина, Ложь, , , Истина, , Ложь, СокрЛП(Выборка.КодПодразделения), 2);
КонецЕсли;
// Делаем окно Word видимым пользователю
ОбъектВорд.Application.Visible = Истина;
ОбъектВорд.Activate();
КонецФункции
При реализации вывода данных в Word полезно учитывать следующие технические нюансы:
Find.Execute в MS Word завершается с ошибкой COM, если подставляемая строка превышает 255 символов (часто встречается в длинных названиях отделений МВД в поле КемВыдан). Если длина строки больше 255 символов, производите замену напрямую через диапазон (Range.Text) или используйте закладки (Bookmarks).
Если Документ.Bookmarks.Exists("КемВыдан") Тогда
Документ.Bookmarks("КемВыдан").Range.Text = СокрЛП(Выборка.КемВыдан);
КонецЕсли;
[КемВыдан] разбивается внутренним форматированием Word на несколько XML-узлов.01.01.0001. Использование формата "ДП=''" гарантирует, что в печатную форму не попадут некорректные пустые даты.