Разработчики 1С часто сталкиваются с задачей автоматизации рутинных операций, таких как печать чеков или выполнение других действий, связанных с функциональностью формы документа. Возникает естественное желание сделать это программно, в фоновом режиме, без необходимости интерактивного открытия самой формы документа. Например, в конфигурации 1С:Управление торговлей 10.3, может потребоваться программно запустить печать чека для документа "Реализация товаров и услуг", не отнимая время у продавцов и не открывая документ на экране.
Давайте подробно разберем, возможно ли это сделать в платформе 1С:Предприятие 8.2 с использованием обычных форм, какие существуют ограничения и какие обходные пути мы можем использовать.
Первое, что мы должны четко понимать, — это принципиальное отличие между объектом данных и формой в 1С. Когда мы получаем документ по ссылке и используем метод ПолучитьОбъект(), мы работаем исключительно с данными документа. Это набор реквизитов, табличных частей, но не с его визуальным представлением и связанным с ним программным кодом формы. Объект документа — это всего лишь «слепок» данных из базы, а не интерактивный элемент пользовательского интерфейса.
Форма документа, напротив, является интерактивным представлением этих данных. Она содержит элементы управления (кнопки, поля ввода), а также модуль формы. В модуле формы находятся процедуры и функции, многие из которых реагируют на действия пользователя (например, нажатие кнопки), инициализируют локальные переменные формы, выполняют клиентский код. Эти процедуры и функции по умолчанию не являются экспортными. Это означает, что они предназначены только для внутреннего использования в контексте самой формы и недоступны для вызова извне – из других модулей, обработок или фоновых заданий.
Таким образом, прямой ответ на вопрос: "Может ли платформа 1С:Предприятие 8.2 (Обычные формы) программно 'открыть' форму документа в фоне (без интерактивного отображения) и 'нажать' на кнопку, которая вызывает неэкспортную процедуру модуля формы?" — Нет, не может. Платформа не предоставляет прямых механизмов для симуляции интерактивных действий пользователя с формой в фоновом режиме. Это подтверждается сообщениями специалистов на форуме: "Нет не может." и "Никаким. Поэтому даже не стоит изобретать велосипед."
Даже если бы мы смогли получить программно объект формы через ПолучитьФорму() (что само по себе для обычных форм не дает полного контекста, как для управляемых), мы бы столкнулись с проблемой вызова неэкспортных процедур, которые зачастую опираются на локальные переменные формы, ее реквизиты и контекст, создаваемый при интерактивном открытии.
Самый правильный, надежный и поддерживаемый способ решения данной задачи — это вынос логики печати чека из модуля формы в экспортную процедуру или функцию, расположенную в более доступном месте. Мы стремимся перенести код, который должен быть выполнен программно, в модуль, который может быть вызван из любого места конфигурации, включая фоновые задания, обработки или другие модули.
Задача печати чека, как было указано, может содержать около 4000 строк кода. Это говорит о том, что функциональность, скорее всего, включает в себя:
Нам необходимо будет провести глубокий анализ существующего кода кнопки "Чек". Мы должны выявить все зависимости: какие реквизиты документа используются, какие локальные переменные формы, какие глобальные функции или объекты. Все, что критично для выполнения логики, должно быть либо передано в новую экспортную процедуру как параметр, либо получено внутри этой процедуры из объекта документа.
Предположим, мы решили создать экспортную процедуру НапечататьЧек(РежимОткрытия = "Интерактивный") в модуле объекта документа "Реализация товаров и услуг".
// Модуль объекта документа "Реализация товаров и услуг"
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// ... существующий код проведения
КонецПроцедуры
// Новая экспортная процедура для печати чека
// Может быть вызвана из фонового задания, внешней обработки и т.д.
Функция НапечататьЧекПрограммно(СсылкаДокумента, Режим = "Интерактивный") Экспорт
ДокументОбъект = СсылкаДокумента.ПолучитьОбъект();
Если ДокументОбъект = Неопределено Тогда
Возврат "Не удалось получить объект документа по ссылке.";
КонецЕсли;
// В этом месте мы должны воспроизвести логику, которая выполняется
// при нажатии на кнопку "Чек" в форме.
// Это потребует анализа и, возможно, копирования/адаптации значительной части кода.
// Пример (упрощенный, требующий доработки):
// 1. Подготовка параметров для вызова подсистемы ТО
ПараметрыПечати = Новый Структура;
ПараметрыПечати.Вставить("Документ", ДокументОбъект);
ПараметрыПечати.Вставить("ИдентификаторОборудования", УправлениеТорговымОборудованием.ПолучитьИдентификаторФискальногоРегистратора()); // Пример
// ... другие параметры, необходимые для формирования чека
Попытка
// Здесь вызываются функции типовой подсистемы торгового оборудования
// Например, из общего модуля "УправлениеТорговымОборудованием"
УправлениеТорговымОборудованием.ПробитьЧек(ПараметрыПечати); // Предполагаемая функция
Возврат "Чек успешно пробит.";
Исключение
Возврат "Ошибка при пробитии чека: " + ОписаниеОшибки();
КонецПопытки;
КонецФункции
// ... другие процедуры и функции модуля объекта
Важно: Процедура ОсновныеДействияФормыЧек(Кнопка) из модуля формы документа не может быть вызвана напрямую. Мы должны взять ее внутреннюю логику и поместить в новую экспортную процедуру, адаптировав ее под серверный контекст, где нет доступа к элементам формы.
Конфигурация 1С:Управление торговлей 10.3, как и другие типовые решения, содержит развитую подсистему для работы с торговым оборудованием, включая фискальные регистраторы. Часто кнопка "Чек" на форме документа не содержит всей 4000-строчной логики печати, а является лишь точкой входа, которая вызывает уже существующие серверные функции из общих модулей, отвечающих за взаимодействие с ФР.
Наш второй путь — это анализ типового кода УТ 10.3, чтобы найти эти "низкоуровневые" функции, которые непосредственно отвечают за фискализацию и пробитие чека. Вместо того чтобы переносить всю логику кнопки, мы можем попробовать вызвать эти функции напрямую. Вероятно, существуют общие модули, такие как УправлениеТорговымОборудованием, ПодключаемоеОборудованиеКлиентСервер или подобные, которые содержат экспортные функции для работы с ККМ.
Мы должны найти процедуру, которая получает данные документа, взаимодействует с драйвером фискального регистратора и отправляет команду на печать. Затем мы можем вызывать эту процедуру из нашей фоновой обработки, передавая ей ссылку на документ и другие необходимые параметры. Это может быть более быстрым решением, чем полный рефакторинг, если основная логика уже вынесена в общие модули типовой конфигурации.
После того как мы подготовили экспортную процедуру (либо в модуле объекта, либо в общем модуле), мы можем использовать внешнюю обработку или, в некоторых случаях, внешнюю печатную форму для ее вызова.
Внешняя обработка — это идеальный инструмент для выполнения фоновых или групповых операций. Мы можем создать обработку, которая будет:
НапечататьЧекПрограммно(СсылкаДокумента).Эта обработка может быть запущена вручную по требованию или даже настроена для выполнения в фоновом режиме по расписанию через РегламентныеЗадания (если конфигурация позволяет и есть необходимые серверные возможности).
// Пример кода в модуле объекта внешней обработки
Процедура ВыполнитьПечатьЧеков() Экспорт
// 1. Получаем ссылки на документы, для которых нужно напечатать чеки
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Проведен = ИСТИНА
| И НЕ РеализацияТоваровУслуг.ЧекПробит"; // Предполагаемый реквизит "ЧекПробит"
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
СсылкаДокумента = Выборка.Ссылка;
// 2. Вызываем экспортную процедуру из модуля объекта документа
// или из общего модуля, которую мы создали на шаге 2.
Результат = Документ.РеализацияТоваровУслуг.НапечататьЧекПрограммно(СсылкаДокумента); // Пример
Сообщить("Для документа " + СсылкаДокумента + ": " + Результат);
// 3. Возможно, нужно обновить статус документа после успешной печати
Если Найти(Результат, "успешно пробит") > 0 Тогда
// Можно обновить реквизит "ЧекПробит" или выполнить другое действие
Попытка
ОбъектДок = СсылкаДокумента.ПолучитьОбъект();
ОбъектДок.ЧекПробит = Истина; // Пример
ОбъектДок.Записать();
Исключение
Сообщить("Не удалось обновить статус документа " + СсылкаДокумента + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
ВПФ, как правило, ориентированы на формирование печатного макета для одного документа. Однако, если вся логика печати чека была вынесена в серверную часть ВПФ (что редко бывает, так как ВПФ больше для формирования именно макетов), теоретически ее можно было бы вызвать программно. Но для массовой фоновой обработки документов внешняя обработка является гораздо более подходящим инструментом.
Как упоминалось в сообщении 17, "Готовая поделка под обычные формы для массовой печати чеков на ФР валяется тут, на сайте. Открывать форму документа и 'нажимать кнопочки' не надо." Это еще раз подчеркивает, что подход с внешней обработкой, вызывающей прямую логику фискализации, является рабочим и распространенным решением.
В контексте управляемых форм (которые появились в платформе 8.2, но не используются в УТ 10.3 в чистом виде), иногда применяется косвенный подход с использованием расширений. Как было показано в сообщении 13, для управляемых форм можно создать расширение и в нем определить экспортную процедуру для формы, которая затем вызовет неэкспортную процедуру этой же формы. Например:
// Пример из сообщения 13, для УПРАВЛЯЕМЫХ ФОРМ (не применимо к УТ 10.3)
// В модуле формы расширения
Процедура МояЭкспортнаяПроцедураДляФормы() Экспорт
// Здесь мы вызываем неэкспортную процедуру исходной формы
ЭтотОбъект.ИмяНеЭкспортнойПроцедурыИсходнойФормы();
КонецПроцедуры
// И вызов извне:
Форма = ПолучитьФорму("Документ.Отпуск.Форма.ФормаДокумента");
Форма.МояЭкспортнаяПроцедураДляФормы();
Однако этот подход не применим напрямую к конфигурации УТ 10.3 по нескольким причинам:
Поэтому, несмотря на то что это интересное концептуальное решение для других версий платформы и типов форм, для нашей задачи в УТ 10.3 мы должны сосредоточиться на рефакторинге и использовании серверного кода.
Мы выяснили, что прямая имитация нажатия кнопки на форме документа в 1С:Управление торговлей 10.3 в фоновом режиме без интерактивного открытия формы невозможна из-за архитектурных ограничений платформы 1С:Предприятие 8.2 с обычными формами.
Однако, существуют эффективные и поддерживаемые обходные пути:
Выбор конкретного решения будет зависеть от глубины анализа существующего кода и готовности модифицировать типовую конфигурацию (если это необходимо для создания экспортных процедур в модулях объектов) или использовать внешние инструменты.