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

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

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

Анализ ситуации: реквизит или данные формы?

Разберем типичную проблему: вы подключаетесь из одной базы к другой через COMConnector, находите нужный элемент справочника (например, Справочники.ОсновныеСредства), обращаетесь к его реквизиту СчетУчета, но получаете пустое значение. При этом, если открыть тот же элемент в базе-источнике через обычное пользовательское приложение, поле «Счет учета» будет заполнено.

Первое, что нам необходимо сделать в такой ситуации, — это проанализировать источник данных на форме. В современных конфигурациях, особенно построенных на базе «Библиотеки стандартных подсистем» (БСП), разработчики часто выносят учетные данные в регистры сведений для обеспечения версионности или разделения учета. В этом случае на форму объекта данные попадают не из самого реквизита справочника, а подтягиваются программно в процедуре ПриЧтенииНаСервере или ПриСозданииНаСервере.

Проанализируем шаги для проверки этой гипотезы:

  1. Откроем конфигуратор базы-источника.
  2. Найдем форму справочника и проверим путь к данным для интересующего нас поля.
  3. Если путь к данным ведет не к Объект.СчетУчета, а к какому-то иному реквизиту формы, значит, значение заполняется динамически.
  4. Проверим код модуля формы на наличие запросов к регистрам (например, к регистру сведений СчетаУчетаОС).

Как показала практика, именно в этом часто кроется «обман» зрения: визуально данные есть, но в физической таблице справочника в поле СчетУчета записано значение ПустаяСсылка.

Особенности передачи ссылочных типов через COM

Допустим, реквизит в базе действительно существует и заполнен. Почему он все равно может не передаваться или отображаться некорректно? Выясним причину, кроющуюся в архитектуре COM-объектов. Когда мы получаем ссылку через COM, мы получаем не саму Ссылка текущей базы, а COM-обертку (объект типа ComObject).

Важно понимать: прямая передача ссылок между базами невозможна, так как ссылки — это уникальные идентификаторы (GUID), которые имеют смысл только внутри конкретной информационной базы. Даже если в обеих базах есть одинаковый план счетов, счета «01.01» в базе «Склад» и в базе «Бухгалтерия» могут иметь совершенно разные внутренние идентификаторы.

Рассмотрим способы корректного получения таких данных:

  1. Получение примитивных типов. Вместо того чтобы пытаться прочитать объект целиком, получим его код или наименование. Это надежнее всего.
    
    // Пример получения кода счета через COM-объект
    СчетСсылкаCOM = ОбъектОС.СчетУчета;
    КодСчета = СчетСсылкаCOM.Код; // Получим строку "01.01"
    
  2. Использование представлений. Если нам нужно просто отобразить данные, можно использовать функцию ПРЕДСТАВЛЕНИЕ().
    
    // В запросе через COM лучше сразу выбирать представление
    ТекстЗапроса = "ВЫБРАТЬ ПРЕДСТАВЛЕНИЕ(ОС.СчетУчета) КАК СчетПредставление ИЗ Справочник.ОсновныеСредства КАК ОС";
    

Выполнение запросов на стороне базы-источника

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


// Устанавливаем соединение (предположим, COMСоединение уже создано)
ЗапросCOM = COMСоединение.NewObject("Запрос");
ЗапросCOM.Текст = 
    "ВЫБРАТЬ
    |   СчетаУчетаОС.СчетУчета.Код КАК КодСчета
    |ИЗ
    |   РегистрСведений.СчетаУчетаОС.СрезПоследних(&Период, ОсновноеСредство = &ОС) КАК СчетаУчетаОС";

ЗапросCOM.SetParameter("Период", ТекущаяДата());
ЗапросCOM.SetParameter("ОС", ОбъектОС_COM); // Передаем COM-ссылку на ОС

Выборка = ЗапросCOM.Execute().Choose();
Если Выборка.Next() Тогда
    КодСчетаСтрокой = Выборка.КодСчета;
    // Теперь в приемнике ищем счет по коду
    СчетВПриемнике = ПланыСчетов.Хозрасчетный.НайтиПоКоду(КодСчетаСтрокой);
КонецЕсли;

Обратите внимание: мы выполняем запрос внутри контекста базы-источника, используя объекты, созданные через COMСоединение.NewObject. Это позволяет нам получить доступ ко всем таблицам базы данных, включая те, которые не связаны напрямую с объектом справочника.

Сериализация как альтернативный метод

Проанализируем еще один способ решения проблемы — использование XDTO-сериализации. Этот метод особенно полезен, если структуры баз идентичны. Вместо того чтобы поштучно вытягивать реквизиты, мы можем сериализовать объект в XML-строку в базе-источнике и десериализовать его в базе-приемнике.

Преимущества этого подхода:

Влияние типа соединения: COMConnector против Application

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

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

← На главную