Почему возникает ошибка "Значение не является значением объектного типа" при печати штрихкода из управляемой формы в 1С?

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

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

Проанализируем ситуацию: у нас есть старая, проверенная обработка печати, которая использует стандартную компоненту 1С для вывода штрихкода. Эта компонента размещена в макете как элемент управления ActiveX. Когда мы пытаемся интегрировать эту печать в новую логику на управляемых формах, например, добавить кнопку печати в форму документа, вызов этого механизма приводит к сбою. Система не может получить доступ к объекту штрихкода в макете, и свойство Объект у рисунка оказывается равным Неопределено.

Анализ проблемы: ActiveX и конфликт архитектур

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

ActiveX — это технология Microsoft, которая позволяет встраивать элементы управления (компоненты) непосредственно в приложения. В нашем случае, это объект для генерации штрихкода, который размещается в макете табличного документа. Важнейшая его особенность — он может работать только на стороне клиента и только в операционной системе Windows.

Когда мы работаем с обычными формами, вся логика исполняется в толстом клиенте. Приложение имеет полный доступ к ресурсам операционной системы, может инициализировать ActiveX-объекты и работать с ними напрямую. Поэтому старая обработка, запущенная как файл, работает без сбоев.

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

  1. На сервере 1С. Часто основная логика формирования печатных форм выносится на сервер для оптимизации. Сервер 1С, особенно если он работает под управлением Linux, ничего не знает об ActiveX. Даже на Windows-сервере у серверного процесса нет пользовательского интерфейса и контекста для инициализации таких компонентов. Попытка обратиться на сервере к Рисунки.Штрихкод.Объект закономерно вернет Неопределено.
  2. На клиенте (тонкий или веб-клиент). Тонкий и веб-клиенты имеют серьезные ограничения по безопасности и кроссплатформенности. Они не поддерживают прямую работу с ActiveX. Платформа 1С сознательно блокирует такие вызовы из управляемых форм, чтобы обеспечить стабильную и безопасную работу в любой среде.

Таким образом, когда мы нажимаем кнопку печати в управляемой форме, исполняемый код пытается обратиться к ActiveX-объекту в той среде (на сервере или в ограниченном клиенте), где он недоступен. Это и есть причина ошибки.

Решение 1: "Обходной маневр" через вызов обычной формы

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

Разберем по шагам, как это реализовать:

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

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


&НаКлиенте
Процедура ПечатьЭтикеткиСоШтрихкодом(Команда)
    
    // Создаем структуру с параметрами для передачи в форму обработки
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("СсылкаНаОбъект", Объект.Ссылка);

    // Открываем форму обработки. Предполагается, что у обработки есть
    // основная форма, и она является ОБЫЧНОЙ формой.
    ОткрытьФорму("Обработка.МояОбработкаПечати.Форма", ПараметрыФормы);

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

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


// Код в модуле ОБЫЧНОЙ формы обработки печати

Процедура ПриОткрытии()
    
    // Проверяем, были ли переданы параметры при открытии
    Если ЭтотОбъект.ПараметрЗапуска <> Неопределено И ТипЗнч(ЭтотОбъект.ПараметрЗапуска) = Тип("Структура") Тогда
        Если ЭтотОбъект.ПараметрЗапуска.Свойство("СсылкаНаОбъект") Тогда
            
            // Заполняем реквизит формы или обработки
            // и сразу запускаем процедуру печати
            СсылкаНаДокумент = ЭтотОбъект.ПараметрЗапуска.СсылкаНаОбъект;
            ПечатьЭтикетки(СсылкаНаДокумент);

            // Можно сразу закрыть форму после печати, если не нужно взаимодействие с пользователем
            Закрыть();
        КонецЕсли;
    КонецЕсли;

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

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

Решение 2: Современный подход с использованием нативных компонент

Предыдущий способ — это скорее обходной путь. Правильным и стратегическим решением будет полный отказ от устаревшей технологии ActiveX в пользу современных нативных (встроенных) компонент 1С для работы со штрихкодами.

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

Проанализируем этот процесс:

  1. Подключение компоненты. Компоненты для разных ОС (Windows, Linux) и разрядностей (x32, x64) хранятся в двоичных макетах конфигурации. Код определяет текущую систему и подключает нужную версию компоненты.
  2. Генерация изображения. Вызывается метод компоненты, который на вход принимает строку для кодирования (сам штрихкод), тип кода (EAN13, Code128 и т.д.) и другие параметры. На выходе этот метод возвращает не объект на форме, а объект типа Картинка.
  3. Вставка картинки в макет. Полученная картинка программно вставляется в нужную область табличного документа.

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

Примерный код (может отличаться в зависимости от конкретной компоненты):


&НаСервере
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект)
    
    // ... код получения макета и вывода областей ...

    // Получаем объект компоненты для работы со штрихкодами
    // Обычно это делается через общий модуль, например, МенеджерОборудованияКлиентСервер.КомпонентаПечатиШтрихкодов()
    КомпонентаШК = ПолучитьКомпоненту(); 

    // Устанавливаем свойства штрихкода
    КомпонентаШК.ТипКода = 10; // Code128
    КомпонентаШК.Сообщение = "4601234567890";
    КомпонентаШК.Высота = 20;
    
    // Генерируем изображение штрихкода
    ИзображениеШК = КомпонентаШК.СоздатьИзображение(); // Метод может называться иначе
    
    // Получаем область макета, куда нужно вставить штрихкод
    ОбластьМакета = Макет.ПолучитьОбласть("Штрихкод");
    
    // Находим в области рисунок и присваиваем ему сгенерированную картинку
    РисунокШК = ОбластьМакета.Рисунки.Штрихкод;
    РисунокШК.Картинка = ИзображениеШК;
    
    ТабДок.Вывести(ОбластьМакета);
    
    Возврат ТабДок;

КонецФункции

Дополнительный фактор: разрядность платформы

Следует также помнить, что старые компоненты печати штрихкодов часто были только 32-разрядными. Если вы запускаете клиент 1С x64, такая 32-разрядная ActiveX компонента просто не зарегистрируется и не будет работать, что приведет к той же самой ошибке. Переход на современный подход с нативными компонентами решает и эту проблему, так как они обычно поставляются в версиях для обеих разрядностей.

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

← На главную