Как получить данные табличной части документа через COMConnector в 1С

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

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

Анализ проблемы: почему не находится документ методом НайтиПоНомеру

Проанализируем исходный код, в котором документ ищется методом менеджера документа:


СсылкаНаОбъект = Соединение.Документы.РеализацияТоваровУслуг.НайтиПоНомеру("01000000001");

Если в конфигурации для нумератора документов установлена периодичность (например, в пределах года), метод НайтиПоНомеру требует указания даты интервала. Выделим основные причины, из-за которых поиск документа дает пустой результат:

  1. Не указан или некорректно передан интервал дат: Если второй параметр опущен, платформа ищет документ в текущем рабочем периоде по умолчанию. Если документ создан в прошлых годах, он найден не будет. При этом передавать число (например, 2014) нельзя — параметр ДатаИнтервала должен иметь строгий тип Дата.
  2. Формат номера и ведущие нули: Номер документа в 1С является строковым реквизитом фиксированной или переменной длины. Если в номере присутствуют префиксы узлов/организаций или ведущие нули, строка в параметре поиска должна точно соответствовать значению в информационной базе.
  3. Отсутствие проверки результата: Метод НайтиПоНомеру не вызывает исключений при отсутствии совпадений, а возвращает пустую ссылку. При передаче такой ссылки в параметры последующего запроса выборка гарантированно окажется пустой.
  4. Ограничения прав доступа (RLS): Если учетная запись, под которой выполняется COM-подключение, ограничена правами чтения по организациям или подразделениям, документ не будет прочитан.

Способ 1. Корректное использование метода НайтиПоНомеру с передачей даты

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


// Формируем дату нужного периода
ДатаПоиска = Дата(2014, 1, 1);

// Ищем документ с явным указанием периода нумерации
СсылкаНаОбъект = Соединение.Документы.РеализацияТоваровУслуг.НайтиПоНомеру("01000000001", ДатаПоиска);

Если Не Соединение.ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
    Сообщить("Документ с указанным номером не найден в заданном периоде!");
    Возврат;
КонецЕсли;

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

Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Сообщить("Строка: " + Выборка.НомерСтроки + " | Код: " + Выборка.Код + " | Количество: " + Выборка.Количество);
КонецЦикла;

Способ 2. Оптимальный выбор данных одним запросом без предварительного поиска ссылки

Разберем по шагам наиболее производительный и правильный архитектурный подход. Выполнять отдельный вызов метода НайтиПоНомеру через COM-соединение избыточно, так как каждое обращение через границу процессов создает накладные расходы. Гораздо эффективнее объединить поиск документа и выборку данных табличной части в единый запрос во внешней базе.

Посмотрим на пример запроса, где условие по номеру и периоду накладывается непосредственно на реквизиты шапки документа через поле Ссылка:


Соединение = ПолучитьПодключениеКФайловойБД();

Если Соединение = Неопределено Тогда
    Возврат;
КонецЕсли;

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

Запрос.УстановитьПараметр("Номер", "01000000001");
Запрос.УстановитьПараметр("ДатаНачала", Дата(2014, 1, 1, 0, 0, 0));
Запрос.УстановитьПараметр("ДатаОкончания", Дата(2014, 12, 31, 23, 59, 59));

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить("Строка: " + Выборка.НомерСтроки + ", Код: " + Выборка.Код + ", Количество: " + Выборка.Количество);
КонецЦикла;

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

Особенности и технические ограничения COM-соединений

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

  1. Разрядность процессов: Разрядность вызывающего приложения (32-разрядный или 64-разрядный клиент/сервер 1С) должна строго соответствовать разрядности зарегистрированной библиотеки comcntr.dll. Если 64-разрядный сервер 1С обращается к 32-разрядному коннектору, потребуется создание COM+ приложения в службах компонентов Windows.
  2. Операционная система: Технология COM поддерживается исключительно в операционных системах семейства Windows. При переносе серверной части на Linux интеграция через COMConnector перестанет работать.
  3. Альтернативные варианты: В современных конфигурациях для межсистемного обмена рекомендуется применять HTTP-сервисы или стандартный интерфейс OData, так как они платформонезависимы и не создают проблем с блокировками COM-библиотек.
← На главную