При разработке внешних печатных форм для конфигураций на управляемых формах (таких как «Розница 2.2», «Управление торговлей 11», «ERP Управление предприятием» и других решений на базе Библиотеки Стандартных Подсистем — БСП) разработчики часто сталкиваются с необходимостью предварительного ввода параметров. Например, перед выводом на печать пользователю нужно выбрать склад, подписанта, настроить вывод цен или логотипа.
Для реализации такой логики создается вспомогательная форма настроек. Однако при попытке ее открыть и передать параметры печати стандартными методами БСП нередко возникает неприятная ошибка: «{ВнешняяОбработка.ВнешняяОбработка1.Форма.ФормаНастроек.Форма(17)}: Поле объекта не обнаружено (ИдентификаторКоманды)». В этой статье мы подробно разберем, почему возникает данная неполадка, проанализируем внутреннее поведение механизмов платформы 1С и БСП, а также построим по шагам правильную, современную и отказоустойчивую схему реализации печатной формы с предварительной настройкой.
Давайте разберемся по шагам, почему стандартный код выдает ошибку и как спроектировать обработку правильно.
---
Для начала проанализируем ситуацию, описанную в первом сообщении темы. Разработчик пытается выполнить следующий код в модуле формы настроек:
КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм(Параметры.ИдентификаторКоманды);
При этом система аварийно завершает работу, сообщая, что у объекта Параметры отсутствует свойство ИдентификаторКоманды. Это происходит по двум ключевым причинам:
Параметры формы содержит только те переменные, которые были явно объявлены на вкладке «Параметры» этой формы в конфигураторе (либо предопределенные системные параметры). Если БСП пытается передать параметры при открытии формы, а в самой форме они не зарегистрированы как параметры, платформа проигнорирует их, и при обращении к ним возникнет ошибка.ПриСозданииНаСервере. Попытка обратиться к ним на клиенте или в неподходящих процедурах часто приводит к ошибкам контекста.СписокЗначений (так как это универсальный интерактивный тип). В то же время классическая процедура печати на сервере ожидает строго массив ссылок (тип Массив). Попытка передать список напрямую приводит к сбою, из-за чего разработчики вынуждены прибегать к методу выгрузки значений, о котором упоминалось в обсуждении.---
Прежде чем писать программный код, необходимо подготовить саму форму настроек нашей внешней обработки в конфигураторе. Откройте форму настроек, перейдите на вкладку «Параметры» (в правом верхнем углу окна редактора формы) и добавьте три обязательных параметра, которые БСП передает при вызове клиентского метода:
Строка) — определяет, какая именно кнопка печати была нажата пользователем (актуально, если в одной обработке зарегистрировано несколько печатных форм).СправочникСсылка.ДополнительныеОтчетыИОбработки) — ссылка на саму внешнюю обработку в справочнике БСП.СписокЗначений или Произвольный) — список документов (или справочников), для которых была вызвана печатная форма.Важно: Для каждого из этих трех параметров в палитре свойств обязательно установите флажок «Ключевой». Это гарантирует, что значения параметров будут корректно инициализированы платформой при открытии формы.
---
В модуле объекта внешней обработки необходимо правильно описать функцию СведенияОВнешнейОбработке(). Для того чтобы управление сначала передавалось в нашу форму настроек, а не напрямую в процедуру печати на сервере, тип использования команды должен быть строго назначен как ВызовКлиентскогоМетода.
Рассмотрим пример правильной структуры регистрации:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.9.20");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.Наименование = "Печатная форма с формой настроек";
ПараметрыРегистрации.БезопасныйРежим = Ложь;
// Добавляем документ-назначение (например, Реализация товаров и услуг)
ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Печать с выбором параметров";
НоваяКоманда.Идентификатор = "ПечатьСНастройками";
// КРИТИЧЕСКИ ВАЖНО: Используем вызов клиентского метода вместо открытия формы или вызова сервера!
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
НоваяКоманда.ПоказыватьОповещение = Истина;
НоваяКоманда.Модификатор = "ПечатьMXL";
Возврат ПараметрыРегистрации;
КонецФункции
При такой регистрации БСП не будет пытаться сразу запустить печать на сервере, а передаст управление в основную форму внешней обработки, которую мы назначим точкой входа.
---
Теперь спроектируем модуль формы настроек. Нам нужно решить три задачи:
Посмотрим на пример реализации модуля формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, что параметры переданы штатно из подсистемы БСП
Если Параметры.Свойство("ИдентификаторКоманды") Тогда
// Записываем параметры БСП в реквизиты нашей формы (их нужно предварительно создать на форме с соответствующими типами)
Объект.ИдентификаторКоманды = Параметры.ИдентификаторКоманды;
КонецЕсли;
Если Параметры.Свойство("ДополнительнаяОбработкаСсылка") Тогда
Объект.ДополнительнаяОбработкаСсылка = Параметры.ДополнительнаяОбработкаСсылка;
КонецЕсли;
Если Параметры.Свойство("ОбъектыНазначения") Тогда
// Поскольку ОбъектыНазначения приходят в виде СпискаЗначений, загружаем их в реквизит формы с типом СписокЗначений
Объект.ОбъектыНазначения.ЗагрузитьЗначения(Параметры.ОбъектыНазначения);
КонецЕсли;
// Здесь можно задать настройки по умолчанию для ваших реквизитов формы
// Например: Объект.ВыводитьЦены = Истина;
КонецПроцедуры
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, МассивОбъектов) Экспорт
// Этот метод вызывается БСП автоматически, если тип команды "ВызовКлиентскогоМетода".
// Нам достаточно просто открыть текущую форму настроек пользователю.
Открыть();
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьПечать(Команда)
// Проверим заполненность ключевых полей настроек перед выводом на печать
Если Не ЗначениеЗаполнено(Объект.ДополнительнаяОбработкаСсылка) Тогда
ВызватьИсключение "Не найдена ссылка на дополнительную обработку в системе БСП!";
КонецЕсли;
// Готовим параметры для открытия стандартной формы предпросмотра БСП "ПечатьДокументов"
ПараметрыОткрытия = Новый Структура("ИсточникДанных, ПараметрыИсточника");
ПараметрыОткрытия.ИсточникДанных = Объект.ДополнительнаяОбработкаСсылка;
ПараметрыИсточника = Новый Структура("ИдентификаторКоманды, ОбъектыНазначения");
ПараметрыИсточника.ИдентификаторКоманды = Объект.ИдентификаторКоманды;
// РЕШЕНИЕ ПРОБЛЕМЫ С СОВМЕСТИМОСТЬЮ ТИПОВ:
// Извлекаем чистый массив ссылок из СпискаЗначений с помощью метода ВыгрузитьЗначения()
ПараметрыИсточника.ОбъектыНазначения = Объект.ОбъектыНазначения.ВыгрузитьЗначения();
// Формируем структуру с пользовательскими настройками, которые были введены на форме
СтруктураНастроек = Новый Структура;
СтруктураНастроек.Вставить("ВыводитьЦены", Объект.ВыводитьЦены);
СтруктураНастроек.Вставить("ВыводитьПодписи", Объект.ВыводитьПодписи);
// Передаем кастомные настройки в специальное свойство БСП "ДополнительныеПараметры"
ПараметрыИсточника.Вставить("ДополнительныеПараметры", СтруктураНастроек);
ПараметрыОткрытия.ПараметрыИсточника = ПараметрыИсточника;
// Открываем стандартное окно предварительного просмотра документов БСП
ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия);
// Закрываем форму настроек, так как пользователь перешел к просмотру печатного листа
Закрыть();
КонецПроцедуры
---
Когда открывается общая форма БСП ПечатьДокументов, система обращается к модулю объекта нашей внешней печатной формы на сервере. Чтобы перехватить переданные настройки и применить их в момент генерации макета, рекомендуется использовать специализированный интерфейс БСП — процедуру ПечатьПоВнешнемуИсточнику.
Рассмотрим структуру модуля объекта внешней обработки:
Процедура ПечатьПоВнешнемуИсточнику(СсылкаНаВнешнююОбработку, ПараметрыИсточника, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Извлекаем переданные с формы параметры настроек
НастройкиНаСервере = Неопределено;
Если ПараметрыИсточника.Свойство("ДополнительныеПараметры") Тогда
НастройкиНаСервере = ПараметрыИсточника.ДополнительныеПараметры;
КонецЕсли;
// Инициализируем коллекцию печатных форм стандартным методом БСП
КоллекцияПечатныхФорм = УправлениеПечатью.ПодготовитьКоллекциюПечатныхФорм(ПараметрыИсточника.ИдентификаторКоманды);
ПараметрыВывода = УправлениеПечатью.ПодготовитьСтруктуруПараметровВывода();
ОбъектыПечати = Новый СписокЗначений;
// Передаем управление в процедуру формирования табличного документа, пробрасывая настройки
СформироватьТабличныйДокумент(ПараметрыИсточника.ОбъектыНазначения, КоллекцияПечатныхФорм, ОбъектыПечати, НастройкиНаСервере);
КонецПроцедуры
Процедура СформироватьТабличныйДокумент(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, НастройкиНаСервере)
// Получаем описание нашей печатной формы из коллекции
ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ПечатьСНастройками");
Если ПечатнаяФорма = Неопределено Тогда
Возврат;
КонецЕсли;
// Создаем результирующий табличный документ
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.АвтоМасштаб = Истина;
// Пример чтения кастомных настроек
ВыводитьЦены = Истина; // значение по умолчанию
Если НастройкиНаСервере <> Неопределено И НастройкиНаСервере.Свойство("ВыводитьЦены") Тогда
ВыводитьЦены = НастройкиНаСервере.ВыводитьЦены;
КонецЕсли;
// Выполняем цикл по объектам печати
Для Каждого ТекущийДокумент Из МассивОбъектов Цикл
// Здесь выполняется стандартный алгоритм получения макета и его заполнения
// С учетом логики переменной ВыводитьЦены
// Регистрируем объект в списке напечатанных
ОбъектыПечати.Добавить(ТекущийДокумент);
КонецЦикла;
// Записываем результат обратно в структуру БСП
ПечатнаяФорма.ТабличныйДокумент = ТабличныйДокумент;
КонецПроцедуры
---
Рассмотренный нами шаблон проектирования внешней обработки с предварительными настройками имеет ряд неоспоримых достоинств перед «кустарными» методами обхода ограничений платформы:
ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ...) и ПечатьПоВнешнемуИсточнику) гарантирует, что при обновлении «1С:Розница» или другой конфигурации ваша печатная форма продолжит работать без ошибок.ВыгрузитьЗначения() полностью страхует решение от ошибок несовместимости типов СписокЗначений и Массив на стороне сервера 1С.Используйте этот шаблон при проектировании печатных форм любой сложности, и вы навсегда забудете о системных ошибках адресации параметров на управляемых формах 1С!