Как исправить ошибку загрузки единиц измерения через COM-соединение в УТ 10.3 и настроить печать этикеток?

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

При организации интеграции между различными конфигурациями «1С:Предприятие» (например, при переносе данных из «Бухгалтерии предприятия» в «Управление торговлей 10.3») разработчики часто используют механизм COM-соединения. Это мощный инструмент, однако при работе с подчиненными справочниками в контексте другого процесса могут возникать неочевидные ошибки.

В этой статье мы подробно разберем, почему при создании документов через COM-соединение в «1С:Управление торговлей 10.3» (УТ 10.3) некорректно заполняются единицы измерения, выясним, почему из-за этого перестает работать типовая печать этикеток и штрихкодов, и найдем наиболее элегантные и производительные способы решения этих проблем.

---

Анализ проблемы: почему стандартное присвоение ЕИ не работает?

Рассмотрим классическую ситуацию. Разработчик пытается заполнить табличную часть создаваемого через COM документа «Оприходование товаров» на основании данных из базы-источника. На первый взгляд код выглядит логичным:


// Попытка прямого заполнения единицы измерения
СомТовары.ЕдиницаИзмерения = СомТовары.Номенклатура.БазоваяЕдиницаИзмерения;

Однако при выполнении этого кода поле ЕдиницаИзмерения в документе остается либо пустым, либо заполняется некорректно, из-за чего документ впоследствии невозможно нормально использовать. Чтобы понять причину, проанализируем структуру хранения данных в УТ 10.3.

В конфигурации «Управление торговлей 10.3» учет единиц измерения построен по двухъярусной схеме:

  1. Классификатор единиц измерения (Справочник.КлассификаторЕдиницИзмерения) — это общесистемный плоский список, содержащий международные и национальные стандарты (штуки, килограммы, литры и т.д.). Реквизит карточки номенклатуры БазоваяЕдиницаИзмерения ссылается именно на этот справочник.
  2. Единицы измерения номенклатуры (Справочник.ЕдиницыИзмерения) — это подчиненный справочник, где владельцем каждого элемента выступает конкретная позиция номенклатуры. Именно здесь хранятся индивидуальные коэффициенты пересчета (например, «коробка» с коэффициентом 10 для товара А).

В табличных частях документов УТ 10.3 в колонке ЕдиницаИзмерения система строго ожидает ссылку на подчиненный справочник ЕдиницыИзмерения, а не на классификатор ОКЕИ. Пытаясь записать туда БазоваяЕдиницаИзмерения, мы нарушаем типизацию метаданных. Документ может записаться (поскольку COM-соединение позволяет обходить некоторые интерактивные проверки платформы), но база данных придет в рассогласованное состояние.

---

Почему не работает стандартный поиск с отбором по Владельцу через COM?

Пытаясь исправить ситуацию, разработчики часто прибегают к поиску по наименованию в подчиненном справочнике с указанием владельца:


СомТовары.ЕдиницаИзмерения = ComConnection.Справочники.ЕдиницыИзмерения.НайтиПоНаименованию(
    строка.ЕдиницаИзмерения.Наименование, 
    , 
    СомТовары.Номенклатура
);

При выполнении этого кода в контексте COM-соединения отбор по владельцу часто попросту игнорируется или возвращает пустую ссылку. Выясним причину этой особенности.

Дело в том, что переменная СомТовары.Номенклатура возвращает прокси-объект COM, в то время как метод НайтиПоНаименованию на стороне COM-сервера ожидает полноценную ссылку типа СправочникСсылка.Номенклатура во внутреннем контексте базы-приемника. Из-за трудностей маршалинга типов между процессами отбор по владельцу сбрасывается. В результате система находит первую попавшуюся единицу измерения с наименованием «шт» или «пар», принадлежащую совершенно другому товару. Это приводит к хаосу в учете: в документе оказывается чужая единица измерения.

---

Варианты решения проблемы с единицами измерения

Рассмотрим два пути решения этой задачи: тот, к которому пришли участники форума, и более профессиональный, оптимальный вариант.

Способ 1. Поиск по коду подчиненной единицы (Решение с форума)

В ходе обсуждения участники пришли к следующей конструкции:


КодЕдиницы = ComConnection.Справочники.Номенклатура.НайтиПоКоду(Строка.Номенклатура.Код).ЕдиницаДляОтчетов.Code;
СомТовары.ЕдиницаИзмерения = ComConnection.Справочники.ЕдиницыИзмерения.НайтиПоКоду(КодЕдиницы);

Плюсы: Этот способ действительно работает. Он позволяет однозначно найти нужную единицу в подчиненном справочнике базы-приемника.

Минусы: Данный код крайне непроизводителен. При обработке каждой строки документа выполняется несколько тяжелых сетевых вызовов через COM: поиск номенклатуры по коду, чтение реквизита единицы отчетов, получение ее кода, а затем повторный поиск единицы по этому коду. На документе в 100 строк это вызовет заметные задержки.

Способ 2. Прямое назначение из реквизитов Номенклатуры (Рекомендуемый способ)

Поскольку мы уже нашли объект номенклатуры в базе-приемнике и присвоили его строке документа (СомТовары.Номенклатура), мы можем мгновенно получить ссылки на связанные с ним единицы измерения. В карточке номенклатуры УТ 10.3 всегда заполнены реквизиты ЕдиницаХраненияОстатков и ЕдиницаДляОтчетов, которые по определению являются элементами подчиненного справочника ЕдиницыИзмерения.

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


// Находим номенклатуру один раз
СсылкаНоменклатуры = ComConnection.Справочники.Номенклатура.НайтиПоКоду(Строка.Номенклатура.Код);

Если НЕ СсылкаНоменклатуры.Пустая() Тогда
    СомТовары = ДокументОбъект.Товары.Добавить();
    СомТовары.Номенклатура = СсылкаНоменклатуры;
    
    // Прямое переопределение без лишних поисков в базе данных!
    СомТовары.ЕдиницаИзмерения = СсылкаНоменклатуры.ЕдиницаХраненияОстатков;
    
    СомТовары.Коэффициент = СсылкаНоменклатуры.ЕдиницаХраненияОстатков.Коэффициент;
    СомТовары.Количество = Строка.Количество;
    СомТовары.Цена = Строка.Цена;
    СомТовары.Сумма = Строка.СуммаВРознице;
КонецЕсли;

Такой подход работает молниеносно, так как мы не делаем ни одного лишнего запроса к базе данных через COM-соединение, а используем уже полученные свойства объекта номенклатуры.

---

Почему товары не выводятся на «Печать этикеток»?

После успешного создания и проведения документа через COM-соединение разработчики часто сталкиваются со следующей проблемой: при попытке открыть обработку «Печать этикеток и ценников» на основании созданного документа табличная часть обработки оказывается пустой.

Разберем три ключевые причины, почему так происходит.

Причина 1. Отсутствие штрихкодов в регистре сведений

Типовая обработка печати этикеток в УТ 10.3 при заполнении из документа использует внутренний запрос, который жестко связывает (соединяет) товары из документа с регистром сведений РегистрСведений.Штрихкоды. Если для перенесенного из другой базы товара штрихкод еще не зарегистрирован в базе УТ 10.3, запрос вернет пустой результат, и строка товара просто не попадет на форму печати.

Решение: При переносе номенклатуры или документов необходимо также программно переносить или генерировать штрихкоды в базе-приемнике.

Причина 2. Несовпадение единицы измерения в регистре штрихкодов и документе

Регистр сведений Штрихкоды в УТ 10.3 имеет ключевое измерение ЕдиницаИзмерения. Штрихкод всегда привязывается к конкретной единице измерения из подчиненного справочника. Если в регистре штрихкод записан для единицы «шт» с кодом УТ0007893, а в созданном документе в поле ЕдиницаИзмерения по ошибке записалась другая копия единицы (например, созданная заново с кодом УТ0011671), то связь в запросе печати этикеток разорвется. Программа посчитает, что для этой единицы измерения штрихкода не существует.

Причина 3. Запись классификатора ОКЕИ вместо подчиненного справочника

Если в коде загрузки документа все-таки осталась запись БазоваяЕдиницаИзмерения (из классификатора), документ запишется, но в регистре штрихкодов данные хранятся в разрезе подчиненного справочника. Сравнение типов в запросе обработки печати выдаст ложь, и этикетка не распечатается.

---

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

Для того чтобы решить обе проблемы разом, рассмотрим полноценный пример кода на стороне базы-источника. Напишем алгоритм, который не только оптимально создает документ оприходования в УТ 10.3 через COM, но и гарантирует создание корректных штрихкодов для последующей беспрепятственной печати этикеток.


// Инициализация подключения к базе УТ 10.3
ComConnector = Новый COMОбъект("V83.COMConnector");
ComConnection = ComConnector.Connect("Srvr=""Server1C"";Ref=""UT_Base"";Usr=""Admin"";Pwd=""Password""");

// Создаем документ Оприходование товаров в УТ 10.3
НовыйДок = ComConnection.Документы.ОприходованиеТоваров.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДата();
НовыйДок.Организация = ComConnection.Справочники.Организации.НайтиПоРеквизиту("ИНН", "7700000000");
НовыйДок.СкладОтравитель = ComConnection.Справочники.Склады.НайтиПоНаименованию("Основной склад");

Для Каждого СтрокаТЧ Из ТоварыКПереносу Цикл
    
    // Находим номенклатуру в УТ
    СомНоменклатура = ComConnection.Справочники.Номенклатура.FindByCode(СтрокаТЧ.НоменклатураКод);
    
    Если СомНоменклатура.IsEmpty() Тогда
        Продолжить; // Если номенклатура не найдена, пропускаем строку или логируем ошибку
    КонецЕсли;
    
    НоваяСтрока = НовыйДок.Товары.Добавить();
    НоваяСтрока.Номенклатура = СомНоменклатура;
    
    // ПРАВИЛЬНО: берем подчиненную единицу измерения напрямую из свойств номенклатуры
    НоваяСтрока.ЕдиницаИзмерения = СомНоменклатура.ЕдиницаХраненияОстатков;
    НоваяСтрока.Коэффициент = СомНоменклатура.ЕдиницаХраненияОстатков.Коэффициент;
    
    НоваяСтрока.Количество = СтрокаТЧ.Количество;
    НоваяСтрока.Цена = СтрокаТЧ.Цена;
    НоваяСтрока.Сумма = СтрокаТЧ.Сумма;
    
    // ПРОВЕРКА И СОЗДАНИЕ ШТРИХКОДА: гарантирует, что этикетка распечатается
    Если Не ПустаяСтрока(СтрокаТЧ.Штрихкод) Тогда
        
        // Ищем штрихкод в регистре сведений УТ 10.3
        РегистрШтрихкодов = ComConnection.РегистрыСведений.Штрихкоды;
        НайденныйШтрихкод = РегистрШтрихкодов.СоздатьМенеджерЗаписи();
        НайденныйШтрихкод.Штрихкод = СтрокаТЧ.Штрихкод;
        НайденныйШтрихкод.Прочитать();
        
        Если Не НайденныйШтрихкод.Выбран() Тогда
            // Если штрихкода нет, создаем новую запись
            НоваяЗаписьШК = РегистрШтрихкодов.СоздатьМенеджерЗаписи();
            НоваяЗаписьШК.Штрихкод = СтрокаТЧ.Штрихкод;
            НоваяЗаписьШК.Владелец = СомНоменклатура;
            // Важно привязать именно к той единице измерения, которая заполнена в документе!
            НоваяЗаписьШК.ЕдиницаИзмерения = СомНоменклатура.ЕдиницаХраненияОстатков;
            НоваяЗаписьШК.ТипШтрихкода = ComConnection.ПланыВидовХарактеристик.ТипыШтрихкодов.EAN13;
            НоваяЗаписьШК.Записать();
        КонецЕсли;
        
    КонецЕсли;

КонецЦикла;

// Записываем и проводим документ
НовыйДок.Записать(ComConnection.РежимЗаписиДокумента.Проведение);
ВызватьИсключение "Документ успешно проведен!";

---

Резюме для разработчика

Для того чтобы избежать ошибок при программном заполнении справочников и табличных частей документов в «1С:Управление торговлей 10.3» через COM-соединение, всегда придерживайтесь следующих правил:

← На главную