При разработке внешних отчетов и печатных форм на базе Системы компоновки данных (СКД) программисты часто сталкиваются с необходимостью вывода подписей ответственных лиц в подвале документа. Это могут быть руководитель организации, главный бухгалтер, кассир, кладовщик или другие материально ответственные лица. Пользователям важно иметь возможность гибко выбирать, кто именно подпишет отчет в данный момент, особенно если должности или временно исполняющие обязанности сотрудники часто меняются.
В этой статье мы подробно разберем, как реализовать удобный и профессиональный механизм выбора подписей в отчетах 1С. Мы пройдем путь от простого ручного ввода параметров до автоматического заполнения по данным регистров сведений, ограничений списков выбора и красивой верстки макета подвала без "висящих подписей".
Давайте проанализируем самый очевидный и простой способ решения проблемы, который обсуждался на форуме. Суть метода заключается в том, чтобы не усложнять текст запроса компоновки данных, а использовать встроенный механизм параметров СКД. Нам не нужно связывать таблицы запроса со справочниками физических лиц или должностей внутри самого SQL-запроса. Достаточно объявить параметры непосредственно в схеме компоновки данных.
Рассмотрим пошагово, как это настроить в конфигураторе:
&ДолжностьРуководителя, &Руководитель, &ДолжностьБухгалтера, &ГлавныйБухгалтер.СправочникСсылка.Должности (или Строка, если в вашей конфигурации должности хранятся в виде текстовых строк).СправочникСсылка.ФизическиеЛица или СправочникСсылка.Сотрудники. Это позволит пользователю выбирать конкретного человека из удобного диалогового окна справочника, а не вводить ФИО вручную каждый раз.Этот подход решает базовую задачу, но заставляет пользователя делать много ручных кликов при каждом формировании отчета. Давайте выясним, как автоматизировать этот процесс. Для более гибкой компоновки интерфейса параметров на форме можно применить способ стыковки элементов управляемой формы с пользовательскими настройками СКД.
В типовых конфигурациях фирмы 1С (таких как ERP, Комплексная автоматизация, Управление торговлей, Бухгалтерия предприятия) информация об ответственных лицах организаций хранится в периодических регистрах сведений. Например, в регистре ОтветственныеЛицаОрганизаций или ОтветственныеЛица. Было бы отличным тоном автоматически подтягивать актуальные подписи на дату формирования отчета по выбранной организации.
Давайте реализуем это через создание дополнительного набора данных-запроса в нашей СКД:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
ОтветственныеЛицаСрезПоследних.ФизическоеЛицо КАК Руководитель,
ОтветственныеЛицаСрезПоследних.Должность КАК ДолжностьРуководителя
ИЗ
РегистрСведений.ОтветственныеЛицаОрганизаций.СрезПоследних(&Период, Организация = &Организация И ОтветственноеЛицо = ЗНАЧЕНИЕ(Перечисление.ОтветственныеЛицаОрганизаций.Руководитель)) КАК ОтветственныеЛицаСрезПоследних
В схеме компоновки данных мы можем связать этот набор данных с основным или же использовать полученные значения для программной инициализации параметров в модуле объекта отчета. Посмотрим на пример кода, который можно поместить в обработчик события ПриКомпоновкеРезультата модуля объекта отчета:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем текущие настройки компоновщика
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Извлекаем значение организации и даты из параметров
ПараметрОрганизация = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Организация"));
ПараметрПериод = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("КонецПериода"));
Если ПараметрОрганизация <> Неопределено И ЗначениеЗаполнено(ПараметрОрганизация.Значение) Тогда
ДатаСреза = ?(ПараметрПериод <> Неопределено И ЗначениеЗаполнено(ПараметрПериод.Значение), ПараметрПериод.Значение, ТекущаяДата());
// Запрос к регистру сведений ответственных лиц
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОтветственныеЛицаСрезПоследних.ФизическоеЛицо КАК Руководитель,
| ОтветственныеЛицаСрезПоследних.Должность КАК Должность
|ИЗ
| РегистрСведений.ОтветственныеЛицаОрганизаций.СрезПоследних(&Период, Организация = &Организация И ОтветственноеЛицо = ЗНАЧЕНИЕ(Перечисление.ОтветственныеЛицаОрганизаций.Руководитель)) КАК ОтветственныеЛицаСрезПоследних";
Запрос.УстановитьПараметр("Организация", ПараметрОрганизация.Значение);
Запрос.УстановитьПараметр("Период", ДатаСреза);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Устанавливаем значения по умолчанию для подписей
ПараметрФИО = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Руководитель"));
Если ПараметрФИО <> Неопределено Тогда
ПараметрФИО.Значение = Выборка.Руководитель;
ПараметрФИО.Использование = Истина;
КонецЕсли;
ПараметрДолж = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ДолжностьРуководителя"));
Если ПараметрДолж <> Неопределено Тогда
ПараметрДолж.Значение = Выборка.Должность;
ПараметрДолж.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Используя этот метод, мы добиваемся того, что при выборе организации и формировании отчета система автоматически заполняет поля подписей актуальными данными, избавляя пользователя от рутины.
Если пользователю все же требуется вручную изменить подписанта, нам нужно сделать этот выбор максимально комфортным. По умолчанию при клике на поле выбора сотрудника открывается весь справочник Сотрудники, содержащий тысячи записей по всем организациям холдинга. Чтобы ограничить этот список только сотрудниками выбранной организации, применим стандартный механизм связей параметров выбора без написания кода.
Разберем, как настроить этот функционал:
&Руководитель (у которого тип значения установлен как СправочникСсылка.Сотрудники).Отбор.ГоловнаяОрганизация (или Отбор.ТекущаяОрганизация в зависимости от структуры метаданных конфигурации), а в колонке Источник настроек укажем наш параметр ПараметрыДанных.Организация.После этой простой настройки платформа автоматически применит фильтр к открывающемуся справочнику сотрудников, и пользователь увидит только тех людей, которые работают в выбранной организации.
Создание кастомных форм отчетов под каждый чих сильно увеличивает стоимость поддержки программного продукта. Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), то крайне рекомендуется использовать штатные механизмы интеграции отчетов.
Вместо переопределения формы мы можем перенести логику инициализации параметров подписей в модуль объекта отчета. Это позволит отчету корректно работать не только при интерактивном формировании пользователем, но и при автоматической рассылке отчетов по расписанию, когда формы вообще не создаются.
Для этого в модуле объекта отчета мы можем переопределить экспортную процедуру, которую вызывает БСП при подготовке настроек:
Процедура ОпределитьНастройкиФормы(Форма, КлючВарианта, Настройки) Экспорт
// Здесь можно указать БСП, какие параметры выносить в быстрые настройки,
// а также динамически изменить состав доступных полей формы.
Настройки.СобытияПриИзмененииПараметров.Вставить("Организация", "ПриИзмененииОрганизацииСервер");
КонецПроцедуры
Этот подход гарантирует высокую стабильность работы отчета и полное соответствие стандартам разработки фирмы 1С. Для практического изучения типовых механизмов вывода подписей и печатей подойдет готовый пример внешней печатной формы на актуальной БСП.
Важно не просто получить ФИО и должность, но и красиво вывести их на печать. Стандартное оформление СКД часто накладывает цветовые схемы (синий, зеленый, серый) на все выводимые группировки. Подписи в подвале отчета должны выглядеть строго, аккуратно и не иметь лишней раскраски или рамок.
Давайте по шагам разберем профессиональную верстку подвала:
ПодвалПодписи.ПодвалПодписи, перейдем на ее вкладку Другие настройки (внизу экрана) и установим свойство Макет оформления в значение Без оформления. Это очистит все стандартные цвета и границы. В свойстве Выводимые поля снимем флаг автозаполнения, чтобы туда случайно не попали детальные поля отчета.ПодвалПодписи, а тип макета выберем Заголовок.[ДолжностьРуководителя] _______________ [Руководитель].ДолжностьРуководителя и Руководитель с соответствующими параметрами данных нашей СКД (&ДолжностьРуководителя и &Руководитель).Использование макетов группировок гарантирует, что блок подписей будет выведен ровно в том визуальном стиле, который вы задали в макете, сохраняя все шрифты, отступы и линии подчеркивания для физической подписи.
Очень распространенная и неприятная проблема: отчет полностью сформировался, таблица заняла всю страницу, а блок подписей перенесся на второй, абсолютно чистый лист. Сдавать такие документы контрагентам или руководству считается дурным тоном. Подписи не должны "висеть" в воздухе отдельно от табличной части.
Решить эту проблему штатными средствами интерактивной настройки СКД невозможно, но мы легко можем справиться с ней с помощью программного вывода табличного документа в модуле объекта отчета.
Рассмотрим детальный пример реализации контроля вывода страниц:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Отключаем стандартный вывод, так как будем выводить отчет вручную
СтандартнаяОбработка = Ложь;
// Инициализируем схему, настройки и процессор компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
// Начинаем вывод
ПроцессорВывода.НачатьВывод();
МассивВыводимыхЭлементов = Новый Массив;
ЭлементыДляКонтроляВывода = Новый Массив;
Пока Истина Цикл
ЭлементРезультата = ПроцессорКомпоновки.Следующий();
Если ЭлементРезультата = Неопределено Тогда
Прервать;
КонецЕсли;
// Нам нужно отловить момент вывода подвала
Если ЭлементРезультата.ЗначенияПараметров.Свойство("ИмяГруппировки")
И ЭлементРезультата.ЗначенияПараметров.ИмяГруппировки.Значение = "ПодвалПодписи" Тогда
// Создаем временный документ для проверки, поместится ли подвал на текущую страницу
ВременныйДокумент = Новый ТабличныйДокумент;
ПроцессорВыводаПодвала = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВыводаПодвала.УстановитьДокумент(ВременныйДокумент);
ПроцессорВыводаПодвала.НачатьВывод();
ПроцессорВыводаПодвала.ВывестиЭлемент(ЭлементРезультата);
ПроцессорВыводаПодвала.ЗакончитьВывод();
// Проверяем, помещается ли подвал вместе с последней выведенной строкой
ЭлементыДляКонтроляВывода.Очистить();
ЭлементыДляКонтроляВывода.Добавить(ВременныйДокумент);
Если Не ДокументРезультат.ПроверитьВывод(ЭлементыДляКонтроляВывода) Тогда
// Если не помещается — принудительно вставляем разрыв страницы,
// чтобы перенести подвал на новый лист вместе с заголовками или итоговой строкой
ДокументРезультат.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
КонецЕсли;
ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
КонецЦикла;
ПроцессорВывода.ЗакончитьВывод();
КонецПроцедуры
С помощью метода ПроверитьВывод() мы гарантируем, что блок подписей никогда не окажется оторванным от контекста отчета. Документ всегда будет выглядеть профессионально и аккуратно сложенным при распечатке на бумажных носителях.
Подводя итог, можно сказать, что простая задача вывода подписей имеет множество уровней реализации. Начиная с базовых параметров в СКД, которые мы рассмотрели на примере обсуждения участников форума, и заканчивая профессиональными механизмами автоматического заполнения по срезу последних регистра сведений, связями параметров выбора и программным контролем разбиения страниц. Используйте данные подходы в своей повседневной практике, чтобы ваши отчеты радовали пользователей удобством, а руководство — безупречным внешним видом документов.