Как правильно перенести единицы измерения при обмене между базами 1С через COM-соединение

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

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

Различие в типах данных: Классификатор против Справочника

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

  1. БазоваяЕдиницаИзмерения — это ссылка на справочник КлассификаторЕдиницИзмерения. Здесь хранятся общероссийские стандарты (штуки, килограммы, метры).
  2. ЕдиницаХраненияОстатков (а также ЕдиницаДляОтчетов или ЕдиницаМест) — это ссылка на справочник ЕдиницыИзмерения, который является подчиненным справочнику Номенклатура.

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


// ОШИБОЧНЫЙ ПОДХОД
НоваяСтрока.ЕдиницаИзмерения = НоваяСтрока.Номенклатура.БазоваяЕдиницаИзмерения; 
// Здесь происходит попытка записи элемента Классификатора в поле Справочника

Создание запроса через COM-соединение

Для того чтобы получить правильную ссылку, нам необходимо найти в подчиненном справочнике ЕдиницыИзмерения тот элемент, который соответствует базовой единице из классификатора. Для этого в базе-источнике (или базе-приемнике, в зависимости от логики обмена) нужно выполнить запрос. Рассмотрим, как правильно инициализировать объекты через COM-соединение.

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


// Правильное создание объекта Запрос во внешней базе
Запрос = БазаИсточник.NewObject("Запрос");

// Если написать "Запрос = Новый Запрос", 
// объект будет создан в текущей базе и не увидит таблицы внешней базы

Проанализируем структуру запроса, который поможет нам найти нужную единицу измерения для конкретной номенклатуры:


Запрос = БазаИсточник.NewObject("Запрос");
Запрос.Текст = 
"ВЫБРАТЬ
|    ЕдиницыИзмерения.Ссылка КАК ЕдИзм
|ИЗ
|    Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
|ГДЕ
|    ЕдиницыИзмерения.Владелец = &Номенклатура
|    И ЕдиницыИзмерения.ЕдиницаПоКлассификатору = &БазоваяЕдиница";

Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылкаCOM);
Запрос.УстановитьПараметр("БазоваяЕдиница", НоменклатураСсылкаCOM.БазоваяЕдиницаИзмерения);

Результат = Запрос.Выполнить().Выгрузить();

Особенности отладки COM-объектов

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

Когда вы получаете данные через COM, вы работаете с прокси-объектами. Чтобы увидеть их реальное значение в табло отладчика, используйте следующие приемы:

Если Результат.Количество() > 0, но после присвоения НоваяСтрока.ЕдиницаИзмерения = Результат[0].ЕдИзм поле остается пустым, убедитесь, что вы не забыли вызвать метод Записать() для объекта документа. В интерфейсе изменения могут не отобразиться до момента фактической записи объекта в базу данных.

Оптимизация: избегаем запросов в цикле

Выполнение запроса для каждой строки документа через COM-соединение — это крайне ресурсоемкая операция. Каждый вызов метода через COM требует времени на пересылку данных между процессами. Если в документе сотни строк, обмен будет «зависать».

Рассмотрим более эффективный алгоритм совместной работы:

  1. Сформируйте массив всей номенклатуры, которая есть в выгружаемом документе.
  2. Выполните один запрос к внешней базе, чтобы получить таблицу соответствий «Номенклатура — ЕдиницаИзмерения» для всех позиций сразу.
  3. Поместите результат во временную таблицу значений или используйте Соответствие для быстрого поиска в памяти текущего сеанса.
  4. При заполнении строк документа просто берите готовое значение из соответствия.

Пример получения данных одним пакетом:


ЗапросВсехЕдиниц = БазаИсточник.NewObject("Запрос");
ЗапросВсехЕдиниц.Текст = 
"ВЫБРАТЬ
|    ЕдиницыИзмерения.Владелец КАК Номенклатура,
|    ЕдиницыИзмерения.Ссылка КАК СсылкаНаЕдИзм
|ИЗ
|    Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
|ГДЕ
|    ЕдиницыИзмерения.Владелец В (&МассивНоменклатуры)
|    И ЕдиницыИзмерения.ЕдиницаПоКлассификатору = ЕдиницыИзмерения.Владелец.БазоваяЕдиницаИзмерения";

ЗапросВсехЕдиниц.УстановитьПараметр("МассивНоменклатуры", МассивСсылокCOM);
ТаблицаЕдиниц = ЗапросВсехЕдиниц.Выполнить().Выгрузить();

Использование уникальных идентификаторов (GUID)

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

Посмотрим на пример логики:


// Получаем GUID единицы в одной базе
УникальныйИдентификаторСтрокой = БазаИсточник.String(ЕдиницаСсылка.УникальныйИдентификатор());

// Находим этот же объект в другой базе
НужнаяСсылка = Справочники.ЕдиницыИзмерения.ПолучитьСсылку(Новый УникальныйИдентификатор(УникальныйИдентификаторСтрокой));

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

Подводя итог, при работе с единицами измерения в УПП через COM-соединение, всегда проверяйте соответствие типов (Классификатор vs Справочник) и используйте методы внешней базы для создания объектов запросов. Это позволит избежать пустых колонок и обеспечит корректность ведения складского учета в целевой базе.

← На главную