В процессе работы с конфигурациями, которые совмещают в себе как старые механизмы на обычных формах, так и новые на управляемых, можно столкнуться с неожиданными ошибками. Одна из таких ситуаций — ошибка «Значение не является значением объектного типа (ТипКода)» при попытке сформировать штрихкод в печатной форме, вызываемой из управляемого интерфейса. При этом тот же самый код, запущенный из старой обработки с обычной формой, работает безупречно. Давайте детально разберем, почему так происходит и как исправить эту проблему.
Проанализируем ситуацию: у нас есть старая, проверенная обработка печати, которая использует стандартную компоненту 1С для вывода штрихкода. Эта компонента размещена в макете как элемент управления ActiveX. Когда мы пытаемся интегрировать эту печать в новую логику на управляемых формах, например, добавить кнопку печати в форму документа, вызов этого механизма приводит к сбою. Система не может получить доступ к объекту штрихкода в макете, и свойство Объект у рисунка оказывается равным Неопределено.
Чтобы понять корень проблемы, нужно вспомнить, как устроена работа с управляемыми формами и чем она отличается от обычных. Основная причина ошибки кроется в технологии, на которой построена старая компонента печати штрихкодов — ActiveX.
ActiveX — это технология Microsoft, которая позволяет встраивать элементы управления (компоненты) непосредственно в приложения. В нашем случае, это объект для генерации штрихкода, который размещается в макете табличного документа. Важнейшая его особенность — он может работать только на стороне клиента и только в операционной системе Windows.
Когда мы работаем с обычными формами, вся логика исполняется в толстом клиенте. Приложение имеет полный доступ к ресурсам операционной системы, может инициализировать ActiveX-объекты и работать с ними напрямую. Поэтому старая обработка, запущенная как файл, работает без сбоев.
Управляемые формы работают в совершенно иной, клиент-серверной парадигме. Это означает, что код может выполняться в разных местах:
Рисунки.Штрихкод.Объект закономерно вернет Неопределено.Таким образом, когда мы нажимаем кнопку печати в управляемой форме, исполняемый код пытается обратиться к ActiveX-объекту в той среде (на сервере или в ограниченном клиенте), где он недоступен. Это и есть причина ошибки.
Это решение, к которому пришел автор в теме на форуме. Оно не является самым современным, но оно простое, быстрое и эффективное, если нужно срочно заставить работать старый механизм без глубокой переработки. Суть заключается в том, чтобы принудительно вернуть выполнение кода в совместимую среду.
Разберем по шагам, как это реализовать:
ОткрытьФорму. В качестве параметров мы передадим ссылку на текущий документ, чтобы обработка знала, для какого объекта нужно печатать этикетку.Посмотрим на пример клиентского кода в управляемой форме:
&НаКлиенте
Процедура ПечатьЭтикеткиСоШтрихкодом(Команда)
// Создаем структуру с параметрами для передачи в форму обработки
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("СсылкаНаОбъект", Объект.Ссылка);
// Открываем форму обработки. Предполагается, что у обработки есть
// основная форма, и она является ОБЫЧНОЙ формой.
ОткрытьФорму("Обработка.МояОбработкаПечати.Форма", ПараметрыФормы);
КонецПроцедуры
Теперь в самой обработке печати, в ее модуле формы, нужно принять эти параметры и запустить печать. Обычно это делается в обработчике события ПриОткрытии.
// Код в модуле ОБЫЧНОЙ формы обработки печати
Процедура ПриОткрытии()
// Проверяем, были ли переданы параметры при открытии
Если ЭтотОбъект.ПараметрЗапуска <> Неопределено И ТипЗнч(ЭтотОбъект.ПараметрЗапуска) = Тип("Структура") Тогда
Если ЭтотОбъект.ПараметрЗапуска.Свойство("СсылкаНаОбъект") Тогда
// Заполняем реквизит формы или обработки
// и сразу запускаем процедуру печати
СсылкаНаДокумент = ЭтотОбъект.ПараметрЗапуска.СсылкаНаОбъект;
ПечатьЭтикетки(СсылкаНаДокумент);
// Можно сразу закрыть форму после печати, если не нужно взаимодействие с пользователем
Закрыть();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Почему это работает? Мы инициируем действие из управляемой формы, но сам критический код, работающий с ActiveX, выполняется внутри окружения обычной формы, которая всегда запускается в режиме толстого клиента. Таким образом, мы "переключаем" контекст исполнения в тот, где старый механизм полностью работоспособен.
Предыдущий способ — это скорее обходной путь. Правильным и стратегическим решением будет полный отказ от устаревшей технологии ActiveX в пользу современных нативных (встроенных) компонент 1С для работы со штрихкодами.
Начиная с платформы 8.3.12 и в современных типовых конфигурациях, используется другой подход. Он заключается в том, что штрихкод не является элементом управления в макете, а генерируется программно в виде картинки, которая затем вставляется в табличный документ.
Проанализируем этот процесс:
Картинка.Этот метод полностью совместим с клиент-серверной архитектурой, так как генерация изображения может происходить на сервере 1С, что значительно повышает производительность и не зависит от клиента.
Примерный код (может отличаться в зависимости от конкретной компоненты):
&НаСервере
Функция СформироватьПечатнуюФорму(СсылкаНаОбъект)
// ... код получения макета и вывода областей ...
// Получаем объект компоненты для работы со штрихкодами
// Обычно это делается через общий модуль, например, МенеджерОборудованияКлиентСервер.КомпонентаПечатиШтрихкодов()
КомпонентаШК = ПолучитьКомпоненту();
// Устанавливаем свойства штрихкода
КомпонентаШК.ТипКода = 10; // Code128
КомпонентаШК.Сообщение = "4601234567890";
КомпонентаШК.Высота = 20;
// Генерируем изображение штрихкода
ИзображениеШК = КомпонентаШК.СоздатьИзображение(); // Метод может называться иначе
// Получаем область макета, куда нужно вставить штрихкод
ОбластьМакета = Макет.ПолучитьОбласть("Штрихкод");
// Находим в области рисунок и присваиваем ему сгенерированную картинку
РисунокШК = ОбластьМакета.Рисунки.Штрихкод;
РисунокШК.Картинка = ИзображениеШК;
ТабДок.Вывести(ОбластьМакета);
Возврат ТабДок;
КонецФункции
Следует также помнить, что старые компоненты печати штрихкодов часто были только 32-разрядными. Если вы запускаете клиент 1С x64, такая 32-разрядная ActiveX компонента просто не зарегистрируется и не будет работать, что приведет к той же самой ошибке. Переход на современный подход с нативными компонентами решает и эту проблему, так как они обычно поставляются в версиях для обеих разрядностей.
В итоге, хотя "обходной маневр" с открытием обычной формы является быстрым решением, для долгосрочной поддержки и развития конфигурации настоятельно рекомендуется переводить устаревшие механизмы печати на современную технологию генерации изображений штрихкодов.