Как заставить внешнюю обработку работать в базовой версии 1С, если типовые модули проверяют имя формы?

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

При разработке внешних обработок для базовых версий конфигураций 1С (таких как «Розница», «УНФ» или «Бухгалтерия») программисты часто сталкиваются с жестким ограничением. В базовых версиях невозможно использовать расширения, а типовые общие модули, отвечающие за работу со штрихкодами, маркировкой (ИС) или торговым оборудованием, содержат строгие проверки типа Если ИмяФормы = "Обработка.РМКУправляемыйРежим.Форма.Форма". Поскольку у внешней обработки полное имя начинается с префикса ВнешняяОбработка..., стандартная логика просто перестает работать.

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

Причина возникновения проблемы: анализ механизмов БСП

Рассмотрим ситуацию на примере подсистемы штрихкодирования. Когда кассир сканирует товар, вызывается процедура общего модуля, которая должна определить, в контексте какого документа или обработки происходит действие. Типичный код в общем модуле выглядит следующим образом:


Процедура ВключитьПоддержкуВидовПродукцииИС(Контекст, ПараметрыСканирования, ВидПродукции) Экспорт
    Если ШтрихкодированиеИСКлиентСервер.ЭтоКонтекстОбъекта(Контекст, "Документ.ЧекККМ") 
        Или ШтрихкодированиеИСКлиентСервер.ЭтоКонтекстОбъекта(Контекст, "Обработка.РМКУправляемыйРежим") Тогда
        ЗаполнитьПараметрыСканированияЧекККМ(Контекст, ПараметрыСканирования, ВидПродукции, Ложь);
    КонецЕсли;
КонецПроцедуры

Проанализируем работу функции ЭтоКонтекстОбъекта. Внутри она обращается к метаданным переданного контекста (вашей формы) и проверяет Контекст.Метаданные().ПолноеИмя(). Если вы запускаете внешнюю обработку, ее полное имя будет, например, ВнешняяОбработка.МоеРМК.Форма.Форма. Условие в общем модуле не выполняется, параметры сканирования не заполняются, и работа с маркированным товаром или торговым оборудованием становится невозможной.

Решение №1: Программная подмена контекста (Метод Proxy)

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

Выясним, что в базовой версии встроенная обработка (например, РМКУправляемыйРежим) физически существует в конфигурации, просто вы хотите использовать свою измененную форму. Мы можем программно создать экземпляр встроенной формы и передать её в качестве параметра Контекст.

Пример реализации на стороне клиента вашей внешней обработки:


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

Важный нюанс: Этот метод требует аккуратности при синхронизации данных. Если общий модуль ожидает наличие определенных реквизитов на форме (например, Объект.КассаККМ), они должны быть заполнены в ФормаКонтекст перед вызовом.

Решение №2: Полное копирование логики (Code Mirroring)

Если подмена контекста не помогает (например, если общие модули используют слишком много неэкспортных процедур или обращаются к серверным методам формы, которые нельзя вызвать удаленно), остается путь «зеркалирования» кода. Рассмотрим, как это сделать правильно.

  1. Анализ дерева вызовов: Необходимо определить все функции общих модулей, которые участвуют в процессе. Если вы вызываете ОбработатьВводШтрихкода, за ней потянутся ЗаполнитьПараметрыСканирования, ОпределитьТипПродукции и так далее.
  2. Копирование в модуль обработки: Вы копируете эти функции непосредственно в модуль вашей внешней обработки (или в её модуль объекта).
  3. Модификация проверок: В скопированном коде вы заменяете жесткие условия на поддержку вашей внешней обработки.

Посмотрим на пример измененного условия в скопированной процедуре:


// Было в типовом модуле:
ИначеЕсли ШтрихкодированиеИСКлиентСервер.ЭтоКонтекстОбъекта(Контекст, "Обработка.РМКУправляемыйРежим") Тогда

// Стало в вашей внешней обработке:
ИначеЕсли ШтрихкодированиеИСКлиентСервер.ЭтоКонтекстОбъекта(Контекст, "Обработка.РМКУправляемыйРежим") 
    Или СтрНайти(Контекст.ИмяФормы, "ВнешняяОбработка.РМКУправляемыйРежим") > 0 Тогда

Этот метод считается наиболее стабильным для базовых версий, так как ваша обработка становится автономной. Однако помните о существенном минусе: при обновлении конфигурации 1С (особенно в части работы с Честным Знаком или ЕГАИС) вам придется вручную обновлять скопированный код во внешней обработке, чтобы он соответствовал новым протоколам обмена.

Решение №3: Использование структуры вместо формы (Duck Typing)

В некоторых случаях 1С позволяет использовать «утиную типизацию». Если процедура общего модуля не проверяет тип объекта через ТипЗнч() или Метаданные(), а просто обращается к свойствам через точку (например, Контекст.Объект.Дата), мы можем передать вместо формы обычную Структуру.

Проанализируем ситуацию: мы создаем структуру, ключи которой повторяют имена реквизитов формы. Рассмотрим пример:


&НаСервере
Функция ПодготовитьКонтекстДляМодуля()
    КонтекстЭмуляция = Новый Структура;
    КонтекстЭмуляция.Вставить("Объект", ЭтаФорма.Объект);
    КонтекстЭмуляция.Вставить("ИмяФормы", "Обработка.РМКУправляемыйРежим.Форма.Форма");
    // Добавляем другие ожидаемые реквизиты
    Возврат КонтекстЭмуляция;
КонецФункции

Этот метод сработает только в том случае, если вызываемый общий модуль написан «либерально» и не содержит жестких проверок метаданных через системные функции. Для подсистем маркировки (ИС) этот способ подходит редко, но для более простых механизмов (например, печати ценников или простых расчетов) он может стать самым быстрым решением.

Практические рекомендации по поддержке решения

Выясним, какой путь выбрать именно вам. Если ваша задача — разовое исправление для клиента на базовой версии, метод с программным созданием встроенной формы (Решение №1) является самым элегантным, так как он минимизирует объем дублированного кода.

Если же вы планируете тиражировать свою внешнюю обработку (например, продавать её на маркетплейсах), то полное копирование логики (Решение №2) будет более надежным, так как вы не будете зависеть от того, открывается ли встроенная форма в конкретной версии сборки 1С и нет ли там ограничений на количество одновременно открытых окон.

Важный совет: При разработке внешнего РМК для базовой версии всегда старайтесь выносить логику взаимодействия с торговым оборудованием в отдельные модули вашей обработки, максимально абстрагируясь от типовых механизмов БСП, где это возможно. Это упростит отладку и поддержку вашего решения в будущем.

← На главную