При разработке внешних печатных форм на платформе «1С:Предприятие 8.3» программисты часто сталкиваются с ситуацией, когда стандартный код, успешно работающий в обычной форме обработки, внезапно выдает ошибку во внешней печатной форме (ВПФ). Одной из самых коварных является ошибка: «Ошибка при вызове метода контекста (ПоказатьВыборИзСписка) по причине: Недопустимое значение параметра (параметр номер '2')». Рассмотрим подробно, почему это происходит и как правильно реализовать выбор варианта печати.
Проанализируем ситуацию. Разработчик создает СписокЗначений, наполняет его элементами и передает в глобальный метод ПоказатьВыборИзСписка(). На первый взгляд, всё верно: второй параметр действительно должен быть списком значений. Однако платформа выбрасывает исключение. Выясним причину этого поведения.
Основная проблема заключается в контексте выполнения. Метод ПоказатьВыборИзСписка — это визуальный метод. Чтобы отобразить выпадающее меню, платформе необходимо «привязать» его к какому-либо активному окну или элементу формы. Во внешней печатной форме, которая вызывается из стандартного подменю «Печать» (БСП), фактически отсутствует активная форма самой обработки — она выполняется в фоновом режиме или в контексте вызывающей формы документа. Если третий параметр метода (ЭлементФормы) не указан, система пытается определить его автоматически, не находит подходящего кандидата в текущем контексте и выдает не совсем очевидную ошибку во втором параметре.
Самый быстрый и эффективный способ обойти проблему — отказаться от глобального метода в пользу метода самого объекта СписокЗначений. Рассмотрим по шагам, как изменить код. Вместо обращения к глобальному контексту мы вызываем метод ПоказатьВыборЭлемента() непосредственно у нашего списка.
Посмотрим на пример реализации:
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, МассивОбъектов) Экспорт
СписокВариантов = Новый СписокЗначений;
СписокВариантов.Добавить("Вариант1", "Печать счета с логотипом");
СписокВариантов.Добавить("Вариант2", "Печать счета без логотипа");
ДополнительныеПараметры = Новый Структура("МассивОбъектов", МассивОбъектов);
ОписаниеОповещения = Новый ОписаниеОповещения("ПечатьЗавершение", ЭтотОбъект, ДополнительныеПараметры);
// Вместо ПоказатьВыборИзСписка(ОписаниеОповещения, СписокВариантов)
// Используем метод самого объекта:
СписокВариантов.ПоказатьВыборЭлемента(ОписаниеОповещения, "Выберите макет для печати");
КонецПроцедуры
Метод ПоказатьВыборЭлемента менее требователен к жесткой привязке к конкретному элементу управления формы в момент вызова, что делает его более стабильным для использования во внешних компонентах и обработках БСП.
Разберем более профессиональный подход. Если ваша задача — дать пользователю выбор из нескольких макетов печати, то делать это через всплывающее окно внутри кода — не самый лучший вариант с точки зрения интерфейса 1С. Библиотека стандартных подсистем (БСП) позволяет зарегистрировать несколько команд печати для одной внешней обработки.
Проанализируем, как это работает. Вместо того чтобы создавать одну команду «Печать счета», которая потом спрашивает «Какой макет?», мы регистрируем в системе сразу две команды: «Счет с логотипом» и «Счет без логотипа». Они обе появятся в меню «Печать» документа.
Рассмотрим пример заполнения таблицы команд в функции СведенияОВнешнейОбработке():
Функция СведенияОВнешнейОбработке() Экспорт
// ... инициализация параметров регистрации ...
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Первая команда
НоваяСтрока = ТаблицаКоманд.Добавить();
НоваяСтрока.Представление = "Отзыв из отпуска (макет 1)";
НоваяСтрока.Идентификатор = "МакетОтзыв";
НоваяСтрока.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
// Вторая команда
НоваяСтрока = ТаблицаКоманд.Добавить();
НоваяСтрока.Представление = "Отмена отпуска (макет 2)";
НоваяСтрока.Идентификатор = "МакетОтмена";
НоваяСтрока.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
// ... заполнение остальных параметров ...
КонецФункции
В этом случае в процедуре Печать вам не нужно показывать никаких списков. Вы просто анализируете параметр ИдентификаторКоманды:
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, МассивОбъектов) Экспорт
Если ИдентификаторКоманды = "МакетОтзыв" Тогда
// Логика печати первого макета
ИначеЕсли ИдентификаторКоманды = "МакетОтмена" Тогда
// Логика печати второго макета
КонецЕсли;
КонецПроцедуры
Преимущества этого метода:
Выясним еще одну важную деталь. Если ваша база работает через веб-клиент (в браузере), использование любых методов Показать... без указания конкретного элемента-владельца может привести к тому, что окно выбора просто не отобразится или закроется сразу после появления. Это связано с тем, что браузер блокирует всплывающие элементы, которые не инициированы явным действием пользователя на конкретном виджете.
Если вы всё же решили использовать ПоказатьВыборИзСписка, старайтесь всегда передавать третий параметр. Во внешней печатной форме им может быть, например, кнопка, с которой была вызвана команда, если у вас есть доступ к форме владельца. Но, как мы выяснили ранее, использование СписокЗначений.ПоказатьВыборЭлемента или разделение на разные команды в БСП является гораздо более надежным решением.
Подведем итог. Если вы столкнулись с ошибкой недопустимого параметра в методе ПоказатьВыборИзСписка внутри внешней печатной формы:
Во-первых, проверьте, действительно ли переменная является СпискомЗначений.
Во-вторых, замените вызов на ВашСписок.ПоказатьВыборЭлемента(ОписаниеОповещения).
В-третьих, рассмотрите возможность регистрации нескольких отдельных команд печати в модуле обработки, чтобы интерфейс программы оставался чистым и предсказуемым для пользователя.