При обновлении платформы 1С:Предприятие 8.3 до актуальных релизов многие пользователи классической конфигурации «Управление торговлей, редакция 10.3» сталкиваются с неприятной проблемой: на печатных формах этикеток, ценников или расходных накладных перестает отображаться штрихкод. Вместо привычных штрихов система выдает ошибку или просто оставляет пустое место. Выясним причину этой проблемы и подробно разберем, как перевести конфигурацию на современную компоненту печати штрихкодов из состава БПО (Библиотеки подключаемого оборудования).
Исторически в УТ 10.3 для формирования штрихкодов использовалась внешняя компонента 1CBarCode (известная в системе как COM-объект V8.Barcod.1), выполненная по технологии ActiveX. Данная технология имеет несколько критических ограничений, которые в современных реалиях делают ее использование невозможным:
1CBarCod.dll является строго 32-разрядной. Современные клиентские приложения 1С все чаще устанавливаются и запускаются в 64-битной версии. 64-битный процесс платформы физически не способен загрузить в свое адресное пространство 32-битный ActiveX-компонент.Простая переустановка программы «1С:Печать штрихкодов» силами системного администратора в данном случае не поможет. Требуется принципиальное изменение подхода и переход на технологию Native API.
Проанализируем, в чем заключается разница между старым и новым подходами к выводу графики штрихкодов на печать:
Перейдем к пошаговому руководству по интеграции компоненты БПО в конфигурацию УТ 10.3.
Для начала нам понадобится сам файл компоненты печати штрихкодов. Проще всего извлечь его из любой современной типовой конфигурации (например, «Управление торговлей, редакция 11», «Бухгалтерия предприятия, редакция 3.0» или чистой конфигурации «1С:Библиотека подключаемого оборудования»).
КомпонентаПечатиШтрихкодов. Этот макет представляет собой ZIP-архив, содержащий библиотеки для разных операционных систем и разрядностей.КомпонентаПечатиШтрихкодов.Теперь нам необходимо написать программный интерфейс для взаимодействия с новой компонентой Native API. Создадим новый общий модуль или добавим функции в существующий неглобальный общий модуль (например, в РаботаТорговогоОборудования или специально созданный модуль ШтрихкодированиеСервер). Свойства модуля должны быть установлены в значение: Сервер, Клиент (обычное приложение).
Рассмотрим подробнее код подключения внешней компоненты из макета:
Функция ПодключитьКомпонентуПечатиШтрихкода() Экспорт
ИмяПути = "ОбщийМакет.КомпонентаПечатиШтрихкодов";
ИмяКласса = "Barcode";
// Пытаемся подключить компоненту по технологии Native API
ПодключениеВыполнено = ПодключитьВнешнююКомпоненту(ИмяПути, "КартинкаШтрихкода", ТипВнешнейКомпоненты.Native);
Если ПодключениеВыполнено Тогда
Попытка
Возврат Новый("AddIn.КартинкаШтрихкода." + ИмяКласса);
Исключение
ЗаписьЖурналаРегистрации("ПечатьШтрихкодов", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось инициализировать объект компоненты: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
Иначе
ЗаписьЖурналаРегистрации("ПечатьШтрихкодов", УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось загрузить внешнюю компоненту печати штрихкодов из макета.");
Возврат Неопределено;
КонецЕсли;
КонецФункции
Далее напишем функцию, которая принимает параметры штрихкода, настраивает компоненту и возвращает готовый объект Картинка:
Функция ПолучитьКартинкуШтрихкода(ЗначениеШК, ТипКода = 1, Ширина = 300, Высота = 120) Экспорт
Компонент = ПодключитьКомпонентуПечатиШтрихкода();
Если Компонент = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
// Проверим готовность графической подсистемы на компьютере клиента
Если Не Компонент.ГрафикаУстановлена Тогда
ЗаписьЖурналаРегистрации("ПечатьШтрихкодов", УровеньЖурналаРегистрации.Предупреждение, , ,
"В системе не установлена графическая библиотека для отрисовки.");
Возврат Неопределено;
КонецЕсли;
// Настраиваем ключевые параметры генерации штрихкода
Компонент.АвтоТип = Ложь;
Компонент.ТипКода = ТипКода; // 1 - это EAN13, 16 - это QR-код (полный список типов см. в документации БПО)
Компонент.ЗначениеКода = СокрЛП(ЗначениеШК);
Компонент.Ширина = Ширина;
Компонент.Высота = Высота;
// Дополнительное оформление отображения текста под штрихкодом
Компонент.ОтображатьТекст = Истина;
Компонент.РазмерШрифта = 9;
Компонент.УголПоворота = 0; // Возможные значения: 0, 90, 180, 270 градусов
// Формируем двоичные данные картинки
Попытка
ДвоичныеДанныеКартинки = Компонент.ПолучитьШтрихкод();
Исключение
ЗаписьЖурналаРегистрации("ПечатьШтрихкодов", УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка формирования изображения штрихкода компонентой БПО: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
Если ДвоичныеДанныеКартинки <> Неопределено Тогда
Возврат Новый Картинка(ДвоичныеДанныеКартинки);
КонецЕсли;
Возврат Неопределено;
КонецФункции
После подготовки кода перейдем к редактированию шаблонов документов или обработок печати (например, обработки ПечатьЭтикетокИЦенников). Нам необходимо убрать старый неработающий ActiveX-объект и встроить вместо него обычный рисунок типа «Картинка».
Штрихкод. Обратите внимание, что свойство «Картинка» должно оставаться пустым.Разберем, как изменить код, формирующий печатную форму. Раньше обращение к элементу ActiveX выглядело примерно следующим образом:
// Устаревший вариант работы с ActiveX
ОбластьМакета = Макет.ПолучитьОбласть("Строка");
Попытка
ОбластьМакета.Рисунки.Штрихкод.Объект.Сообщение = ТекущийШтрихкод;
Исключение
// Обработка ошибки отсутствия компоненты
КонецПопытки;
ТабДок.Вывести(ОбластьМакета);
Этот код больше работать не будет, так как у обычного рисунка «Картинка» нет свойства Объект и вложенного параметра Сообщение. Перепишем логику вывода, используя написанную нами ранее экспортную функцию получения изображения:
// Новый кроссплатформенный вариант с использованием Native API БПО
ОбластьМакета = Макет.ПолучитьОбласть("Строка");
// Для качественного отображения без размытия передадим точные размеры области из макета
// Размеры рисунка в макете задаются в миллиметрах, переведем их в пиксели (приблизительно)
ШиринаРисункаПикс = Округлить(ОбластьМакета.Рисунки.Штрихкод.Ширина * 3.779);
ВысотаРисункаПикс = Округлить(ОбластьМакета.Рисунки.Штрихкод.Высота * 3.779);
// Получаем картинку штрихкода из нашей новой функции
КартинкаШтрихкода = ПолучитьКартинкуШтрихкода(ТекущийШтрихкод, 1, ШиринаРисункаПикс, ВысотаРисункаПикс);
Если КартинкаШтрихкода <> Неопределено Тогда
// Заполняем рисунок макета сгенерированной картинкой
ОбластьМакета.Рисунки.Штрихкод.Картинка = КартинкаШтрихкода;
Иначе
// Если картинку получить не удалось, можно очистить рисунок или вывести текстовое сообщение
ОбластьМакета.Рисунки.Штрихкод.Картинка = Новый Картинка;
КонецЕсли;
ТабДок.Вывести(ОбластьМакета);
При печати больших объемов данных (например, при запуске обработки печати 1000 ценников за один раз) инициализация внешней компоненты на каждой итерации цикла приведет к резкому замедлению работы системы и перегрузке оперативной памяти. Проанализируем, как оптимизировать этот процесс.
Для этого рекомендуется кэшировать экземпляр подключенной внешней компоненты, инициализируя ее один раз перед началом цикла печати. Рассмотрим пример оптимизированного кода в обработке печати ценников:
// Создаем переменную для хранения кэшированного экземпляра компоненты
Перем мКомпонентаПечати;
Процедура ПечатьЭтикетокИЦенников()
// Пытаемся подключить и инициализировать компоненту один раз перед циклом
мКомпонентаПечати = ПодключитьКомпонентуПечатиШтрихкода();
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("Этикетка");
Для Каждого СтрокаТовара Из ТоварыНаПечать Цикл
ОбластьМакета = Макет.ПолучитьОбласть("ОбластьШтрихкода");
ШиринаПикс = Округлить(ОбластьМакета.Рисунки.Штрихкод.Ширина * 3.779);
ВысотаПикс = Округлить(ОбластьМакета.Рисунки.Штрихкод.Высота * 3.779);
// Передаем кэшированную компоненту в оптимизированную функцию генерации
КартинкаШК = ПолучитьКартинкуШтрихкодаБыстро(мКомпонентаПечати, СтрокаТовара.Штрихкод, 1, ШиринаПикс, ВысотаПикс);
Если КартинкаШК <> Неопределено Тогда
ОбластьМакета.Рисунки.Штрихкод.Картинка = КартинкаШК;
КонецЕсли;
ТабДок.Вывести(ОбластьМакета);
КонецЦикла;
ТабДок.Показать("Печать этикеток");
КонецПроцедуры
Функция ПолучитьКартинкуШтрихкодаБыстро(Компонент, ЗначениеШК, ТипКода, Ширина, Высота)
Если Компонент = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Компонент.АвтоТип = Ложь;
Компонент.ТипКода = ТипКода;
Компонент.ЗначениеКода = СокрЛП(ЗначениеШК);
Компонент.Ширина = Ширина;
Компонент.Высота = Высота;
Компонент.ОтображатьТекст = Истина;
Компонент.РазмерШрифта = 9;
Попытка
ДвоичныеДанные = Компонент.ПолучитьШтрихкод();
Если ДвоичныеДанные <> Неопределено Тогда
Возврат Новый Картинка(ДвоичныеДанные);
КонецЕсли;
Исключение
// Исключаем падение всего цикла печати при ошибке одного штрихкода
КонецПопытки;
Возврат Неопределено;
КонецФункции
Если вам требуется срочно восстановить работоспособность печати штрихкодов «прямо сейчас», а времени на переписывание программного кода и макетов в конфигураторе нет, можно воспользоваться временными административными мерами:
C:\Program Files (x86)\1cv8\... (а не C:\Program Files\1cv8\...). Старая компонента 1CBarCode сможет работать только в рамках 32-разрядного клиента.regsvr32 "C:\Program Files (x86)\1C\1CBarCode\1CBarCod.dll"
Примечание: путь к файлу библиотеки может отличаться в зависимости от версии установленной утилиты печати штрихкодов.
Важно понимать, что данные административные меры являются лишь временным решением. С выходом новых релизов платформы стабильность работы устаревшей технологии ActiveX будет только снижаться, поэтому полноценный переход на Native API компоненту БПО является наиболее надежным и стратегически верным решением для долгосрочной эксплуатации 1С:Управление торговлей 10.3.