Как во внешней печатной форме 1С запретить печать непроведенного документа и предложить его провести?

Программист 1С v8.3 (Управляемые формы)
← На главную

Разберем распространенную ситуацию: после обновления конфигурации 1С внешняя печатная форма (ВПФ) стала позволять печать непроведенных документов, хотя раньше такой возможности не было. Это может приводить к ошибкам, так как печатная форма может содержать некорректные данные, если документ не сформировал движений по регистрам.

Основная задача — не просто запретить печать, а восстановить стандартное поведение платформы: когда пользователь пытается распечатать непроведенный документ, система должна выводить диалоговое окно с предложением «Провести и закрыть», «Провести» или «Отмена». Проанализируем, как этого добиться.

Решение 1: Использование штатного механизма «ПроверкаПроведенияПередПечатью»

В современных версиях платформы и Библиотеки стандартных подсистем (БСП) существует встроенный механизм для контроля печати непроведенных документов. Он является наиболее правильным и предпочтительным решением.

Суть механизма: при регистрации команды печати для ВПФ вы можете указать специальный флаг ПроверкаПроведенияПередПечатью. Если установить его в значение Истина, платформа возьмет контроль на себя. При попытке печати непроведенного документа она автоматически покажет пользователю стандартный диалог для проведения.

Как реализовать:

В модуле менеджера вашей внешней печатной формы необходимо корректно описать команды печати в процедуре ДобавитьКомандыПечати. Эта процедура вызывается из экспортной функции СведенияОВнешнейОбработке.

Посмотрим на пример из обсуждения. Пользователь пытался добавить колонку в таблицу команд вручную, что может не сработать в зависимости от версии БСП.


// Некорректный или устаревший пример, который может не сработать
Функция ПолучитьТаблицуКоманд()
    Команды = Новый ТаблицаЗначений;
    Команды.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
    Команды.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево"));
    Команды.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка"));
    // Попытка добавить колонку вручную
    Команды.Колонки.Добавить("ПроверкаПроведенияПередПечатью", Новый ОписаниеТипов("Булево")); 
    Возврат Команды;
КонецФункции

Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = "", ПроверкаПроведенияПередПечатью)
    НоваяКоманда = ТаблицаКоманд.Добавить();
    НоваяКоманда.Представление = Представление;
    НоваяКоманда.Идентификатор = Идентификатор;
    НоваяКоманда.Использование = Использование;
    НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
    НоваяКоманда.Модификатор = Модификатор;
    // И установить ее значение
    НоваяКоманда.ПроверкаПроведенияПередПечатью = ПроверкаПроведенияПередПечатью; 
КонецПроцедуры

Более правильный и современный подход, соответствующий БСП, выглядит так. В процедуре ДобавитьКомандыПечати, которая принимает на вход таблицу команд уже с определенными колонками, нужно просто заполнить соответствующее поле.

Пример корректной реализации:


Функция СведенияОВнешнейОбработке() Экспорт
    
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.5.8.1");
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
    ПараметрыРегистрации.Назначение = ПолучитьНазначениеОбработки();
    ПараметрыРегистрации.Наименование = "Моя ВПФ (с проверкой проведения)";
    ПараметрыРегистрации.Версия = "1.1";
    ПараметрыРегистрации.БезопасныйРежим = Истина;
    ПараметрыРегистрации.Информация = "Печатная форма с обязательной проверкой проведения документа";
    
    // Регистрация команды
    Команда = ПараметрыРегистрации.Команды.Добавить();
    Команда.Представление = "Печать акта (с проверкой)";
    Команда.Идентификатор = "АКТ_С_ПРОВЕРКОЙ";
    Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
    Команда.ПоказыватьОповещение = Истина;
    
    // Вот ключевая строка!
    Команда.ПроверкаПроведенияПередПечатью = Истина;
    
    Возврат ПараметрыРегистрации;
    
КонецФункции

Почему это может не работать?

  1. Обновление конфигурации. Возможно, в общих модулях (например, УправлениеПечатью) были сделаны доработки, которые игнорируют этот флаг для ВПФ.
  2. Устаревшая версия БСП. В вашей конфигурации может использоваться старая версия библиотеки, где этот механизм работал иначе или отсутствовал.
  3. Ошибки в самой платформе. Хотя и редко, но такое возможно.

Если штатный способ не дал результата, переходим к обходным путям.

Решение 2: Ручная проверка проведения в процедуре «Печать»

Этот метод не покажет стандартный диалог, но позволит надежно заблокировать печать непроведенных документов. Вы сами контролируете логику проверки в коде ВПФ.

Логика действий:

  1. В основной процедуре Печать(...), которая формирует табличный документ, нужно перебрать все объекты, переданные для печати.
  2. Для каждого объекта проверить его свойство Проведен.
  3. Если документ не проведен, вы можете его проигнорировать, вывести сообщение пользователю или прервать выполнение печати.

Пример кода:

В этом примере мы просто пропустим непроведенные документы. Пользователь не получит для них печатную форму.


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

    Для Каждого СсылкаНаОбъект Из МассивОбъектов Цикл
        
        // Проверяем, проведен ли документ
        Если НЕ СсылкаНаОбъект.Проведен Тогда
            // Сообщаем пользователю, что документ пропущен
            ТекстСообщения = "Документ " + СсылкаНаОбъект + " не проведен и не будет напечатан.";
            Сообщить(ТекстСообщения);
            
            // Переходим к следующему документу в списке
            Продолжить;
        КонецЕсли;
        
        // Если проверка пройдена, формируем и выводим печатную форму
        ТабличныйДокумент = СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати);
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
            КоллекцияПечатныхФорм,
            "ИдентификаторПФ",
            "ПредставлениеПФ",
            ТабличныйДокумент);
            
    КонецЦикла;

КонецПроцедуры

Важный недостаток: как уже отмечалось, этот способ не предлагает пользователю провести документ. Он просто ставит его перед фактом, что печать невозможна. Это может быть неудобно, если нужно распечатать много документов, часть из которых окажется непроведенной.

Решение 3: Программное проведение документа перед печатью

Это компромиссный вариант, который в итоге выбрал автор вопроса на форуме. Суть в том, чтобы попытаться провести документ принудительно прямо из кода печатной формы.

Внимание! Этот подход следует использовать с осторожностью. Проведение документа — ответственная операция, которая может завершиться ошибкой (не хватает остатков, не заполнены поля и т.д.). Пользователь может не ожидать, что при нажатии на кнопку "Печать" в системе будут изменены данные.

Пример реализации:


Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт

    Для Каждого СсылкаНаОбъект Из МассивОбъектов Цикл
        
        Если НЕ СсылкаНаОбъект.Проведен Тогда
            // Если документ не проведен, пытаемся его провести
            Попытка
                ОбъектДокумента = СсылкаНаОбъект.ПолучитьОбъект();
                ОбъектДокумента.Записать(РежимЗаписиДокумента.Проведение);
                
                // Сообщаем об успехе
                Сообщить("Документ " + СсылкаНаОбъект + " был успешно проведен перед печатью.");
                
            Исключение
                // Если провести не удалось, сообщаем об ошибке и пропускаем
                ТекстОшибки = "Не удалось провести документ " + СсылкаНаОбъект + ". " + ОписаниеОшибки();
                Сообщить(ТекстОшибки);
                Продолжить;
            КонецПопытки;
        КонецЕсли;

        // Формируем печатную форму для проведенного документа
        ТабличныйДокумент = СформироватьПечатнуюФорму(СсылкаНаОбъект, ОбъектыПечати);
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, ...);

    КонецЦикла;

КонецПроцедуры

Этот способ автоматизирует процесс, но лишает пользователя контроля. Он лучше, чем простая блокировка, но хуже, чем стандартный диалог.

Решение 4: Доработка через расширение конфигурации

Это самый сложный, но и самый мощный способ, если штатный механизм не работает из-за особенностей типовой конфигурации. Он позволяет "починить" логику, не снимая конфигурацию с поддержки.

Идея:

  1. Найти в конфигурации общий модуль, который отвечает за вызов внешних печатных форм (часто это УправлениеПечатью или подобные).
  2. Найти процедуру, где происходит формирование и вызов ВПФ.
  3. С помощью расширения добавить в эту процедуру заимствованный код проверки проведения из типовых механизмов печати, который будет срабатывать и для ВПФ.

Этот путь требует глубокого понимания архитектуры конфигурации и механизма расширений. Он рекомендуется только опытным разработчикам, когда другие способы не помогают, а восстановить стандартное поведение платформы критически важно.

← На главную