При разработке дополнительных отчетов и обработок в среде 1С:Предприятие 8 на базе Библиотеки Стандартных Подсистем (БСП) программисты часто сталкиваются с задачей размещения внешней печатной формы или отчета в стандартном меню «Печать» какого-либо справочника или документа. В процессе реализации этой задачи может возникнуть популярная ошибка: «Вид обработки, указанный в сведениях о внешней обработке, не соответствует ее расширению». В данной статье мы подробно разберем, почему возникает эта ошибка, как устроены механизмы регистрации БСП и рассмотрим три практических способа интеграции внешнего отчета в командный интерфейс справочника.
Для начала проанализируем архитектуру Библиотеки Стандартных Подсистем. В БСП существует жесткое разграничение типов подключаемых внешних файлов в зависимости от их расширения:
.epf). Могут регистрироваться с видами: "ПечатнаяФорма", "ЗаполнениеОбъекта", "СозданиеСвязанныхОбъектов" и др. Только файлы с расширением .epf и зарегистрированные как "ПечатнаяФорма" система БСП способна автоматически поместить в стандартное меню «Печать» объекта конфигурации..erf). Могут регистрироваться только с видами: "Отчет" или "ДополнительныйОтчет". Механизм БСП размещает такие объекты в меню «Отчеты» формы списка или объекта, либо в дополнительном меню «Еще — Дополнительные отчеты».Если мы попытаемся зарегистрировать файл отчета (.erf) с параметром регистрации Вид = "ПечатнаяФорма", система незамедлительно выдаст ошибку несоответствия расширения. Прямым образом вставить внешний отчет формата .erf в кнопку печати стандартными средствами БСП невозможно. Тем не менее, эту задачу можно решить тремя обходными путями. Рассмотрим каждый из них по шагам.
Это самый популярный и правильный с точки зрения юзабилити способ, если пользователям критически важно видеть ваш отчет именно под кнопкой «Печать». Мы перенесем схему компоновки данных (СКД) внутрь внешней обработки и настроим ее вывод в табличный документ.
Выполним следующие действия по шагам:
.epf) в конфигураторе.ОсновнаяСхемаКомпоновкиДанных) и настроим в нем наш отчет.
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
// Указываем вид "ПечатнаяФорма", чтобы обработка попала в меню "Печать"
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
МассивНазначений = Новый Массив;
МассивНазначений.Добавить("Справочник.Сотрудники"); // Указываем нужный справочник
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "Печать отчета по сотруднику");
ПараметрыРегистрации.Вставить("Информация", "Отчет формируется на базе схемы компоновки данных");
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
// Создаем таблицу команд
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Добавляем команду печати
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = "Сформировать отчет (СКД)";
НоваяКоманда.Идентификатор = "ОтчетСКДПечать";
НоваяКоманда.Использование = "ВызовСерверногоМетода"; // Вызываем метод модуля объекта
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL"; // Указываем стандартный модификатор для печатных форм
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
Теперь нам необходимо написать процедуру обработки этой команды. БСП при вызове команды печатной формы ищет в модуле объекта экспортную процедуру Печать. Реализуем программный запуск нашей СКД внутри этой процедуры:
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Проверяем, наша ли команда вызвана
УправлениеПечатью = ОбщегоНазначения.ОбщийМодуль("УправлениеПечатью");
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ОтчетСКДПечать");
Если ПечатнаяФорма <> Неопределено Тогда
// Создаем табличный документ для вывода результата
ТабДок = Новый ТабличныйДокумент;
ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ОтчетСКД";
// Запускаем формирование отчета по СКД
СформироватьОтчетПоСКД(ТабДок, МассивОбъектов);
ПечатнаяФорма.ТабличныйДокумент = ТабДок;
ПечатнаяФорма.СинонимМакета = "Отчет по сотруднику";
КонецЕсли;
КонецПроцедуры
Процедура СформироватьОтчетПоСКД(ТабличныйДокумент, МассивОбъектов)
// Получаем схему компоновки из макетов внешней обработки
СхемаКомпоновки = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
// Инициализируем настройки по умолчанию
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;
// Устанавливаем отбор по переданным объектам (например, по сотрудникам)
ПараметрОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ПараметрОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
ПараметрОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
ПараметрОтбора.ПравоеЗначение = МассивОбъектов;
ПараметрОтбора.Использование = Истина;
// Компонуем макет
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);
// Выполняем компоновку данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// Выводим результат в табличный документ
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
При таком подходе отчет СКД будет формироваться по выделенным в списке или открытым на форме элементам справочника и выводиться в стандартную форму просмотра печатных форм 1С. В качестве основы для разработки структуры можно использовать готовый пример внешней печатной формы на базе актуальной версии БСП.
Если переделывать отчет в обработку нецелесообразно (например, отчет очень сложный, имеет множество настроек и пользователь должен иметь возможность интерактивно управлять отборами), мы можем зарегистрировать файл с расширением .erf по всем правилам БСП с видом "Отчет".
При такой регистрации кнопка вызова отчета автоматически появится не в меню «Печать», а в командной панели формы справочника под кнопкой «Отчеты» или в подменю «Еще — Дополнительные отчеты».
Рассмотрим структуру модуля объекта для регистрации внешнего отчета:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
// Указываем вид "Отчет"
ПараметрыРегистрации.Вставить("Вид", "Отчет");
МассивНазначений = Новый Массив;
МассивНазначений.Добавить("Справочник.Сотрудники");
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "Справка по сотруднику (внешний отчет)");
ПараметрыРегистрации.Вставить("Версия", "1.1");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Команда открытия формы отчета
НоваяКоманда = ТаблицаКоманд.Добавить;
НоваяКоманда.Представление = "Справка по сотруднику (внешний отчет)";
НоваяКоманда.Идентификатор = "ОткрытьВнешнийОтчет";
НоваяКоманда.Использование = "ОткрытиеФормы"; // Открываем основную форму отчета
НоваяКоманда.ПоказыватьОповещение = Ложь;
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
Функция ПолучитьТаблицуКоманд()
Команды = Новый ТаблицаЗначений;
Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
Возврат Команды;
КонецФункции
Поскольку мы вызываем отчет из конкретного объекта или списка справочника, пользователю будет неудобно заново выбирать сотрудника в параметрах отчета. Механизм БСП автоматически передает в открываемую форму отчета параметр ОбъектыНазначения, содержащий массив выбранных ссылок. Нам остается лишь перехватить его в модуле основной формы нашего отчета.
Проанализируем код модуля формы внешнего отчета:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, передан ли контекст вызова из справочника
Если Параметры.Свойство("ОбъектыНазначения") И ТипЗнч(Параметры.ОбъектыНазначения) = Тип("Массив") Тогда
Если Параметры.ОбъектыНазначения.Количество() > 0 Тогда
// Получаем ссылку на переданный элемент справочника
ВыбранныйОбъект = Параметры.ОбъектыНазначения[0];
// Находим нужный параметр или элемент отбора в настройках компоновщика отчета
Для Каждого ЭлементОтбора Из Отчет.КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если Строка(ЭлементОтбора.ЛевоеЗначение) = "Сотрудник" Тогда
ЭлементОтбора.ПравоеЗначение = ВыбранныйОбъект;
ЭлементОтбора.Использование = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот способ позволяет сохранить весь стандартный функционал отчета СКД (варианты отчетов, настройки пользователя, расшифровки), при этом автоматически подставляя нужный контекст при открытии из справочника.
Если проектные требования жестко регламентируют наличие кнопки вызова именно внешнего отчета (в формате .erf) прямо на форме элемента или списка справочника, стандартного функционала БСП будет недостаточно. В этой ситуации мы задействуем механизм расширений конфигурации.
Разберем алгоритм настройки этого решения:
ФормаЭлемента справочника Сотрудники).ВызватьВнешнийОтчет, и разместим соответствующую ей кнопку на командной панели формы (можно расположить её рядом со стандартной группой кнопок печати).
&НаКлиенте
Процедура Расш1_ВызватьВнешнийОтчет(Команда)
// Формируем массив с текущей ссылкой справочника для передачи в отчет
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(Объект.Ссылка);
// Находим ссылку на зарегистрированный дополнительный отчет на сервере
СсылкаНаОтчет = ПолучитьСсылкуНаДополнительныйОтчет();
Если ЗначениеЗаполнено(СсылкаНаОтчет) Тогда
// Подготавливаем параметры для БСП-команды вызова формы
ВыполняемаяКоманда = Новый Структура;
ВыполняемаяКоманда.Вставить("Ссылка", СсылкаНаОтчет);
ВыполняемаяКоманда.Вставить("Идентификатор", "ОткрытьВнешнийОтчет"); // Идентификатор команды из СведенияОВнешнейОбработке
ВыполняемаяКоманда.Вставить("Представление", "Справка по сотруднику");
// Используем экспортный метод БСП для открытия отчета с передачей контекста
ДополнительныеОтчетыИОбработкиКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ДополнительныеОтчетыИОбработкиКлиент");
ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьОткрытиеФормыОбработки(ВыполняемаяКоманда, ЭтаФорма, МассивОбъектов);
Иначе
ПоказатьПредупреждение(, "Дополнительный отчет не зарегистрирован в справочнике дополнительных обработок!");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСсылкуНаДополнительныйОтчет()
// Ищем отчет по наименованию или предопределенному реквизиту
Возврат Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Справка по сотруднику (внешний отчет)");
КонецФункции
Использование расширений позволяет полностью кастомизировать интерфейс взаимодействия пользователя с внешними отчетами, обходя внутренние ограничения подсистемы БСП по привязке форматов файлов к кнопкам командной панели. Для организации вызова пригодится универсальная процедура программного запуска дополнительных обработок и отчетов средствами БСП.
Мы подробно проанализировали ограничения платформы при работе со сведениями о внешних разработках и рассмотрели три эффективных метода решения проблемы:
.epf) с программным выводом СКД в табличный документ."Отчет" (.erf) и перехватываем объекты назначения при открытии.