При работе с COM-соединением для обмена данными между информационными базами 1С, мы часто сталкиваемся с задачей импорта ссылочных полей, таких как ссылки на справочники, документы или другие объекты. Однако, как показывает практика, прямая передача ссылок из одной базы в другую через COM-объект не работает так, как мы могли бы ожидать. Давайте разберем эту ситуацию подробнее и найдем эффективные решения.
Представим, что у нас есть задача: выкачать данные из справочника «ШтрихКоды» из «той» базы в «эту» базу. Этот справочник содержит поле «Материал», которое является ссылкой на справочник «Номенклатура». Мы выполняем COM-соединение, формируем COM-запрос и получаем результат, но поле «Материал» оказывается пустым или содержит COM-объект, который мы не можем напрямую использовать как ссылку в нашей текущей базе.
Выясним причину этой проблемы. Ссылки в 1С — это абстракции, уникальные для конкретной информационной базы. Каждая ссылка (например, СправочникСсылка.Номенклатура) является внутренним идентификатором объекта внутри своей базы данных. Когда мы получаем объект из другой базы через COM-соединение, мы получаем не саму ссылку, а так называемый COM-объект-прокси. Этот COM-объект представляет удаленный элемент, но не является ссылкой, которая может быть непосредственно использована в нашей текущей базе. Прямое присвоение такого COM-объекта полю типа «Ссылка» в нашей базе невозможно, так как он не является валидным для нашей информационной базы.
Рассмотрим пример запроса, который мы можем выполнить в удаленной базе через COM-соединение:
ВЫБРАТЬ
ШтрихКоды.Ссылка,
ШтрихКоды.Код,
ШтрихКоды.Материал.Ссылка КАК Материал
ИЗ
Справочник.ШтрихКоды КАК ШтрихКоды
В этом запросе мы пытаемся получить саму ссылку на «Материал». Даже если мы напишем ШтрихКоды.Материал КАК Материал, результат будет тем же — мы получим COM-объект. Когда мы пытаемся вставить данные из такого результата в справочник в нашей базе, поле «Материал», которое должно быть ссылкой, остается пустым, потому что COM-объект не может быть интерпретирован как ссылка в текущей базе.
Вот как может выглядеть часть результата, где поле «Материал» пустое, хотя в исходной базе оно было заполнено:
Ссылка Код Материал
000000000001 000000000001
000000000002 000000000002
000000000003 000000000003
Для корректного импорта ссылочных данных нам необходимо изменить подход. Вместо попытки прямой передачи ссылок, мы должны извлекать из COM-объекта уникальные идентификаторы или другие базовые типы данных (строки, числа, даты, булево), по которым мы сможем однозначно найти или создать соответствующий объект в нашей целевой базе.
Давайте рассмотрим основные методы:
Самый надежный и предпочтительный способ — это использование УникальногоИдентификатора (GUID). Каждый объект в 1С имеет уникальный идентификатор, который является глобально уникальным и не меняется при переносе или создании объектов, если только его не изменить специально. Этот GUID позволяет однозначно идентифицировать объект в любой базе.
Шаг 1: Получаем УникальныйИдентификатор из COM-объекта в исходной базе.
В нашем COM-запросе в "той" базе, вместо того чтобы пытаться получить саму ссылку, мы должны извлечь уникальный идентификатор материала. Это делается с помощью метода УникальныйИдентификатор(), доступного для ссылочных типов.
// Пример запроса для получения GUID материала
ВЫБРАТЬ
ШтрихКоды.Ссылка,
ШтрихКоды.Код,
ШтрихКоды.Материал.УникальныйИдентификатор КАК ИдентификаторМатериала
ИЗ
Справочник.ШтрихКоды КАК ШтрихКоды
После выполнения этого запроса через COM-соединение, мы получим табличный документ или набор данных, где в поле "ИдентификаторМатериала" будет строка с GUID.
Шаг 2: Находим или создаем объект по УникальномуИдентификатору в целевой базе.
Получив GUID в "этой" базе, мы можем использовать его для поиска соответствующего объекта в нашем справочнике "Номенклатура". Для этого служит метод НайтиПоУникальномуИдентификатору().
// Пример кода в "этой" базе для обработки полученных данных
Для Каждого СтрокаРезультата Из РезультатЗапросаПоCOM Цикл
// Получаем GUID материала из полученных по COM данных
GUIDМатериала = СтрокаРезультата.ИдентификаторМатериала;
СсылкаНаМатериалВЭтойБазе = Справочники.Номенклатура.НайтиПоУникальномуИдентификатору(GUIDМатериала);
Если СсылкаНаМатериалВЭтойБазе = Неопределено Тогда
// Если объект по GUID не найден, возможно, его еще нет в "этой" базе.
// Здесь мы можем либо создать новый элемент, либо пропустить.
// В случае создания, желательно также сохранить этот GUID
// для будущих сопоставлений или обменов.
// Например, создать новый элемент и заполнить его поля,
// включая возможное хранение GUID исходной базы в дополнительном реквизите.
НовыйМатериал = Справочники.Номенклатура.СоздатьЭлемент();
// Допустим, мы также получаем Наименование и Код материала из COM-объекта
// COMОбъектМатериал = СтрокаРезультата.Материал; // Если Материал тоже был передан как COM-объект
// НовыйМатериал.Код = COMОбъектМатериал.Код;
// НовыйМатериал.Наименование = COMОбъектМатериал.Наименование;
НовыйМатериал.Записать();
СсылкаНаМатериалВЭтойБазе = НовыйМатериал.Ссылка;
Сообщить("Создан новый материал по GUID: " + GUIDМатериала);
КонецЕсли;
// Теперь у нас есть корректная ссылка на материал в "этой" базе
// Мы можем использовать ее для заполнения нашего справочника "ШтрихКоды"
НовыйШтрихКод = Справочники.ШтрихКоды.СоздатьЭлемент();
НовыйШтрихКод.Код = СтрокаРезультата.Код; // Получаем код штрихкода из COM
НовыйШтрихКод.Материал = СсылкаНаМатериалВЭтойБазе;
НовыйШтрихКод.Записать();
Сообщить("Импортирован штрихкод: " + НовыйШтрихКод.Код);
КонецЦикла;
Если по каким-то причинам использование GUID невозможно или нежелательно (хотя это редкость), мы можем использовать другие уникальные реквизиты справочника, такие как Код или Наименование. Этот метод менее надежен, так как код или наименование могут быть неуникальными или меняться, но в простых случаях может быть применен.
Шаг 1: Получаем Код или Наименование из COM-объекта в исходной базе.
В запросе мы извлекаем нужные реквизиты:
// Пример запроса для получения Кода и Наименования материала
ВЫБРАТЬ
ШтрихКоды.Ссылка,
ШтрихКоды.Код,
ШтрихКоды.Материал.Код КАК КодМатериала,
ШтрихКоды.Материал.Наименование КАК НаименованиеМатериала
ИЗ
Справочник.ШтрихКоды КАК ШтрихКоды
Шаг 2: Находим или создаем объект по Коду/Наименованию в целевой базе.
В "этой" базе мы используем методы НайтиПоКоду() или НайтиПоНаименованию().
// Пример кода в "этой" базе для обработки полученных данных
Для Каждого СтрокаРезультата Из РезультатЗапросаПоCOM Цикл
// Получаем Код и Наименование материала
КодМатериала = СтрокаРезультата.КодМатериала;
НаименованиеМатериала = СтрокаРезультата.НаименованиеМатериала;
// Поиск по коду (предполагаем, что код уникален для номенклатуры)
СсылкаНаМатериалВЭтойБазе = Справочники.Номенклатура.НайтиПоКоду(КодМатериала);
Если СсылкаНаМатериалВЭтойБазе = Неопределено Тогда
// Если по коду не найден, можно попробовать по наименованию или создать новый
// СсылкаНаМатериалВЭтойБазе = Справочники.Номенклатура.НайтиПоНаименованию(НаименованиеМатериала);
// Если все еще Неопределено, создаем новый
НовыйМатериал = Справочники.Номенклатура.СоздатьЭлемент();
НовыйМатериал.Код = КодМатериала;
НовыйМатериал.Наименование = НаименованиеМатериала;
НовыйМатериал.Записать();
СсылкаНаМатериалВЭтойБазе = НовыйМатериал.Ссылка;
Сообщить("Создан новый материал по коду: " + КодМатериала);
КонецЕсли;
// Дальнейшее заполнение справочника "ШтрихКоды" аналогично предыдущему примеру
// ...
КонецЦикла;
Важный момент: Мы видим, что COM-объект, полученный для ссылочного поля, не является пустым. Он имеет свойства, к которым мы можем обратиться через точку. Например, если Материал – это COM-объект, представляющий элемент справочника, то мы можем получить Материал.Код, Материал.Наименование, Материал.УникальныйИдентификатор() и другие доступные реквизиты удаленного объекта.
Хотя COM-соединение может быть удобным для быстрых, одноразовых задач, особенно когда обе базы находятся на одной машине и у вас есть административные права, для более сложных, масштабируемых или кроссплатформенных решений рекомендуется рассмотреть другие механизмы обмена данными. Давайте кратко рассмотрим их:
Этот метод является одним из самых распространенных. Мы выгружаем данные из одной базы в структурированный файл (например, в формате XML или JSON). Затем этот файл загружается в другую базу. Этот подход гибок, не зависит от прямого соединения баз и хорошо поддерживается типовыми конфигурациями 1С. Для ссылочных полей в файле мы также выгружаем уникальные идентификаторы (GUID) или другие ключевые поля, а при загрузке используем их для поиска или создания объектов.
Для более продвинутой интеграции между различными информационными системами или распределенными базами 1С используются HTTP-сервисы или веб-сервисы. Эти механизмы позволяют обмениваться данными через интернет, поддерживают различные форматы данных и могут быть настроены для работы с различными платформами. Они обеспечивают высокую гибкость, безопасность и независимость от физического расположения баз данных. При таком обмене также передаются уникальные идентификаторы объектов, по которым происходит сопоставление.
В 1С есть встроенный, мощный и гибкий механизм планов обмена, который специально разработан для синхронизации данных между распределенными информационными базами. Он позволяет тонко настраивать правила обмена, включая сопоставление ссылок между базами (создание, поиск по GUID или другим полям, обработка конфликтов). Этот механизм является стандартом для поддержки распределенных систем 1С и рекомендуется для регулярных и сложных обменов.
Мы видим, что выбор метода обмена зависит от масштаба задачи, требований к надежности, скорости и кроссплатформенности. Для небольших, "одноразовых" задач COM-соединение с правильной обработкой ссылок вполне применимо, но для серьезных систем следует рассмотреть более специализированные инструменты.
При импорте данных через COM-соединение, особенно когда речь идет о ссылочных полях, мы должны помнить, что ссылки уникальны для каждой информационной базы. Прямое присвоение COM-объекта, представляющего ссылку из другой базы, в ссылочное поле текущей базы невозможно. Вместо этого, мы должны извлекать из COM-объекта уникальные идентификаторы (GUID) или другие уникальные реквизиты (код, наименование). Затем, в нашей целевой базе, мы используем эти идентификаторы для поиска уже существующих объектов или для создания новых, после чего уже присваиваем корректную ссылку на найденный или созданный объект.
Этот подход обеспечивает правильное сопоставление данных и целостность информационной базы при интеграции через COM-соединение.