При разработке внешних печатных форм (ВПФ) на платформе 1С:Предприятие 8.3 с использованием Библиотеки стандартных подсистем (БСП) разработчики часто сталкиваются со следующей задачей: необходимо запретить печать документа, если в нем не заполнены определенные реквизиты (например, склад, договор, ответственный) или документ не соответствует нужным условиям (например, не проведен).
Если в стандартном серверном методе печати просто прервать выполнение или вернуть пустое значение (Неопределено), система БСП выдаст пугающую пользователя ошибку: «В обработчике печати не был сформирован табличный документ для...». Это происходит потому, что БСП жестко контролирует заполнение коллекции печатных форм.
В этой статье мы подробно разберем, как правильно обойти это ограничение, рассмотрим три практических способа отмены печати в зависимости от реквизитов документа и научимся правильно отлаживать такие печатные формы.
---
Если мы хотим оставить стандартный механизм БСП с типом команды ВызовСерверногоМетода, то самым простым и безопасным решением будет возврат специального табличного документа-заглушки вместо штатного макета. Это предотвратит возникновение системной ошибки платформы.
Давайте проанализируем, как реализовать этот подход в модуле объекта вашей внешней печатной формы. Вместо того чтобы вызывать ошибку БСП, мы сформируем лаконичный табличный документ с предупреждением для пользователя.
Разберем пример кода в процедуре Печать модуля объекта ВПФ:
Процедура Печать(МассивОбъектовНазначения, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Определяем параметры макета
ПараметрыПечати = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ВнешняяПечатнаяФорма");
Если ПараметрыПечати <> Неопределено Тогда
// Проверяем условия заполнения реквизитов для каждого документа
Для Каждого СсылкаНаДокумент Из МассивОбъектовНазначения Цикл
Отказ = Ложь;
ОписаниеОшибки = "";
// Выполняем проверку реквизитов документа
Если Не ЗначениеЗаполнено(СсылкаНаДокумент.ДоговорКонтрагента) Тогда
Отказ = Истина;
ОписаниеОшибки = "В документе " + Строка(СсылкаНаДокумент) + " не заполнен обязательный реквизит 'Договор'!";
ИначеЕсли СсылкаНаДокумент.Проведен = Ложь Тогда
Отказ = Истина;
ОписаниеОшибки = "Документ " + Строка(СсылкаНаДокумент) + " должен быть проведен для выполнения печати!";
КонецЕсли;
Если Отказ Тогда
// Создаем дружелюбный документ-заглушку
ТабДокПредупреждение = Новый ТабличныйДокумент;
// Оформляем сообщение для пользователя в самом табличном документе
Область = ТабДокПредупреждение.Область("R2C2:R5C10");
Область.Объединить();
Область.Текст = ОписаниеОшибки;
Область.ЦветТекста = WebЦвета.Красный;
Область.Шрифт = Новый Шрифт(Область.Шрифт, , 12, Истина);
Область.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
Область.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
// Выводим заглушку в коллекцию форм, чтобы БСП не выдавала системную ошибку
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ВнешняяПечатнаяФорма",
"Внимание: Ошибка печати!",
ТабДокПредупреждение
);
// Дополнительно выводим сообщение на экран пользователя
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки);
Иначе
// Если все условия выполнены, формируем стандартный макет
ТабДок = СформироватьПечатнуюФорму(СсылкаНаДокумент, ОбъектыПечати);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"ВнешняяПечатнаяФорма",
"Наша печатная форма",
ТабДок
);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
При таком подходе пользователь не увидит аварийных окон платформы. Вместо этого перед ним откроется стандартное окно предпросмотра, где крупным красным шрифтом будет написано, по какой причине печать не может быть выполнена.
---
Наиболее изящным и правильным с точки зрения UX (пользовательского опыта) решением является проверка реквизитов еще до того, как БСП начнет инициализировать и открывать форму печати документов. Для этого мы можем перевести команду печати на работу через клиентский метод.
Рассмотрим по шагам, как это реализовать:
Шаг 1. Настройка регистрации ВПФ
В модуле объекта внешней обработки в функции СведенияОВнешнейОбработке() укажем, что наша команда печати использует вызов клиентского метода:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
// Заполняем базовые свойства
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
ПараметрыРегистрации.Версия = "1.0";
// Добавляем команду
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Печать с проверкой реквизитов";
НоваяКоманда.Идентификатор = "ПечатьСПроверкой";
// Указываем тип вызова - Клиентский метод!
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовКлиентскогоМетода();
НоваяКоманда.ПоказыватьОповещение = Истина;
Возврат ПараметрыРегистрации;
КонецФункции
Шаг 2. Создание формы обработки
Создадим в нашей внешней обработке форму и назначим ее Основной формой. На самой форме визуально ничего размещать не нужно — она будет использоваться исключительно как контейнер для кода.
Шаг 3. Реализация логики в модуле формы
В модуле созданной формы пропишем экспортную процедуру Печать, которая будет принимать управление при нажатии пользователем кнопки печати в документе:
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
// 1. Проверяем заполнение реквизитов на сервере
РезультатПроверки = ПроверитьЗаполнениеДокументовНаСервере(ОбъектыНазначенияМассив);
Если РезультатПроверки.ЕстьОшибки Тогда
// Показываем пользователю предупреждение и прекращаем работу
ПоказатьПредупреждение(, РезультатПроверки.ТекстОшибки);
Возврат; // Форма печати БСП даже не откроется!
КонецЕсли;
// 2. Если проверка пройдена, открываем стандартное окно печати БСП вручную
ПараметрыОткрытия = Новый Структура("ИсточникДанных, ПараметрыИсточника");
ПараметрыОткрытия.ИсточникДанных = Параметры.ДополнительнаяОбработкаСсылка;
ПараметрыИсточника = Новый Структура("ИдентификаторКоманды, ОбъектыНазначения");
ПараметрыИсточника.ИдентификаторКоманды = ИдентификаторКоманды;
ПараметрыИсточника.ОбъектыНазначения = ОбъектыНазначенияМассив;
ПараметрыОткрытия.ПараметрыИсточника = ПараметрыИсточника;
ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьЗаполнениеДокументовНаСервере(МассивДокументов)
Результат = Новый Структура;
Результат.Вставить("ЕстьОшибки", Ложь);
ResultОшибки = Новый Массив;
Для Каждого ДокСсылка Из МассивДокументов Цикл
// Считываем нужные реквизиты напрямую из базы данных
ДанныеДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ДокСсылка, "Проведен, ДоговорКонтрагента, Склад");
Если Не ЗначениеЗаполнено(ДанныеДокумента.ДоговорКонтрагента) Тогда
ResultОшибки.Добавить("В документе " + Строка(ДокСсылка) + " не заполнен договор.");
КонецЕсли;
Если ДанныеДокумента.Проведен = Ложь Тогда
ResultОшибки.Добавить("Документ " + Строка(ДокСсылка) + " должен быть проведен.");
КонецЕсли;
КонецДляОчереди;
Если ResultОшибки.Количество() > 0 Тогда
Результат.ЕстьОшибки = Истина;
Результат.ТекстОшибки = СтрСоединить(ResultОшибки, Символы.ПС);
КонецЕсли;
Возврат Результат;
КонецФункции
Этот способ является наиболее приоритетным в современной разработке, так как он полностью контролирует интерфейс и не производит лишних серверных вызовов по генерации пустого окна печати.
---
Если вам требуется максимально быстро внедрить проверку "в две строчки кода" и вы не хотите создавать форму для клиентского метода, можно использовать механизм аварийного прерывания транзакции на сервере.
В этом случае в модуле объекта внешней печатной формы при обнаружении ошибок заполнения мы вызываем исключение с помощью оператора ВызватьИсключение:
Если Не ДокументГотовКПечати Тогда
ВызватьИсключение "Печать отклонена: Договор контрагента не прошел финансовое согласование!";
КонецЕсли;
БСП автоматически перехватит данное исключение на клиенте. Процесс формирования печатной формы прервется, а текст вашей ошибки отобразится в стандартном диалоговом окне предупреждения 1С.
Важное примечание: Используйте этот метод с осторожностью. Диалоговое окно с ошибкой выполнения может быть воспринято конечными пользователями как критический сбой программы («баг»), что увеличит количество обращений в службу технической поддержки.
---
Многие разработчики тратят много времени, постоянно загружая обработку в справочник «Дополнительные отчеты и обработки» для проверки условий выполнения кода. На самом деле, отладку ВПФ с логикой проверок реквизитов можно сделать очень простой и быстрой.
Выполним следующие шаги:
ДокументСсылка.ЗаказПокупателя) и кнопку «Проверить печать».
&НаКлиенте
Процедура ПроверитьПечатьНажатие(Кнопка)
// Формируем массив из одной тестовой ссылки
МассивДокументов = Новый Массив;
МассивДокументов.Добавить(Объект.ТестовыйДокументСсылка);
// Напрямую вызываем процедуру печати нашей формы
Печать("ПечатьСПроверкой", МассивДокументов);
КонецПроцедуры
Теперь мы можем запустить сеанс «1С:Предприятие» в режиме отладки, открыть нашу обработку напрямую через меню Файл -> Открыть, выбрать нужный документ на форме и нажать кнопку. Мы сможем ставить любые точки останова в конфигураторе, пошагово отслеживать заполнение реквизитов и проверять корректность работы условий.
При этом, когда мы зарегистрируем готовую обработку в справочнике дополнительных обработок в пользовательском режиме, БСП будет использовать только предопределенный экспортный программный интерфейс, а наша отладочная форма просто не будет задействована обычными пользователями.