Как перенести значение из справочника (ссылка) в строку при обмене данными в 1С?

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

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

Анализ проблемы: почему возникает ошибка Поле объекта не обнаружено

Рассмотрим ситуацию, когда при загрузке данных система выдает ошибку: Поле объекта не обнаружено (Наименование). Проанализируем причину. Обычно это происходит при попытке обратиться к свойству объекта, который на самом деле объектом не является. Например, если переменная содержит не ссылку на справочник, а неопределенное значение, пустую строку или таблицу значений (ТЗ), созданную механизмом выгрузки.

В самописных обработках часто используются функции-посредники для получения данных из XML или COM-соединения. Посмотрим на пример функции, которая извлекает значения из таблицы реквизитов:


Функция ПолучитьЗначениеИзТаблРекв(ВхТаблРекв, ВхИмяРеквизита, ВхДопПризнак = "", ВхСоздаватьЕслиНеНайден = ИСТИНА)
    Если НЕ ЗначениеЗаполнено(ВхТаблРекв) Тогда
        Возврат "";
    КонецЕсли;
    _СтрТаблРекв = ВхТаблРекв.Найти(ВхИмяРеквизита, "ИмяРеквизита");
    Если _СтрТаблРекв = Неопределено Тогда
        Возврат ""; 
    ИначеЕсли Лев(_СтрТаблРекв.ТипРеквизита, 16) = "СправочникСсылка" Тогда
        // Здесь часто заложена логика поиска или СОЗДАНИЯ ссылки в текущей базе
        Возврат ПолучитьСсылкуСпр(_СтрТаблРекв.Значение, _СтрТаблРекв.ТипРеквизита, ВхДопПризнак);
    Иначе
        Возврат _СтрТаблРекв.Значение;
    КонецЕсли;
КонецФункции

Если в базе-приемнике реквизит является строкой, использование такой функции может привести к тому, что ПолучитьСсылкуСпр начнет искать или создавать элемент справочника, который нам не нужен. Нам нужно только его текстовое представление.

Способ 1: Получение наименования на стороне приемника

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


// Безопасное получение наименования
СтрокаТЧ.ВариантИсполнения = ?(ЗначениеЗаполнено(ВариантИсполнения), ВариантИсполнения.Наименование, "");

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

Способ 2: Извлечение текста из таблицы параметров обмена

Часто в сложных обменах данные передаются в виде вложенных таблиц. Если в таблице реквизитов по ключу "ВариантИсполнения" лежит не ссылка, а еще одна таблица или массив с данными объекта, нам нужно применить поиск по структуре. Рассмотрим пример кода, который ищет нужное строковое значение в ТЗ, не пытаясь создать объект в справочнике:


Отбор = Новый Структура;
Отбор.Вставить("ИмяРеквизита", "ВариантИсполнения");
// Ищем строку с реквизитом во внутренней таблице данных строки ТЧ
СтрокиПоиска = СтрокаТаблТЧ.Значение.НайтиСтроки(Отбор);

Если СтрокиПоиска.Количество() > 0 Тогда
    // Допустим, значение хранится в первой колонке найденной строки
    ДанныеВИ = СтрокиПоиска[0].Значение;
    
    // Если ДанныеВИ — это тоже коллекция (например, ТЗ с полями Код, Наименование)
    // Извлекаем именно наименование по индексу или имени колонки
    Если ТипЗнч(ДанныеВИ) = Тип("ТаблицаЗначений") И ДанныеВИ.Количество() > 0 Тогда
        СтрокаТЧ.ВариантИсполнения = ДанныеВИ[0].Значение; // Берем текст
    Иначе
        СтрокаТЧ.ВариантИсполнения = Строка(ДанныеВИ);
    КонецЕсли;
КонецЕсли;

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

Способ 3: Корректировка выгрузки на стороне базы-источника

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

  1. Найдем в базе-источнике (ERP) модуль, отвечающий за формирование XML или пакета данных для обмена.
  2. В месте, где заполняется значение для реквизита ВариантИсполнения, заменим передачу ссылки на передачу наименования.
  3. Используем конструкцию Строка(Ссылка.Наименование) или Ссылка.Наименование.

Это позволит функции ПолучитьЗначениеИзТаблРекв в приемнике сразу определить тип как «Строка» и вернуть готовый текст без вызова процедур поиска в справочниках.

Использование стандартных функций преобразования

Для универсальности кода рекомендуется всегда использовать встроенную функцию Строка(). В 1С она работает следующим образом: если в нее передана ссылка, она возвращает основное представление (наименование или код). Если передан пустой объект, она вернет пустую строку. Это избавляет от множества проверок Если ... Тогда.


// Универсальный и безопасный способ
ЗначениеДляЗагрузки = ПолучитьЗначениеИзТаблРекв(ТаблРекв, "ВариантИсполнения");
СтрокаТЧ.ВариантИсполнения = СокрЛП(Строка(ЗначениеДляЗагрузки));

Разберем, почему мы добавили СокрЛП(). При обмене данными, особенно через текстовые форматы, могут возникать невидимые пробелы или символы переноса строк. Функция СокрЛП() гарантирует, что в реквизит документа попадет чистый текст без лишних отступов.

Рекомендация по архитектуре обмена

Если подобные задачи возникают часто, стоит рассмотреть переход на использование конфигурации «1С:Конвертация данных» (КД 2.0 или 3.0). В КД задача преобразования ссылки в строку решается установкой одного флага в правилах конвертации свойств (ПКС). Система сама сформирует оптимальный код, который извлечет наименование из источника и запишет его в строку приемника, корректно обработав все исключения и пустые ссылки.

Резюме: Чтобы перенести значение из ссылки в строку, необходимо либо явно обращаться к свойству Наименование (с проверкой на заполненность), либо использовать функцию Строка(), либо — что наиболее правильно — подготовить строковое значение еще на стороне базы-источника, чтобы приемник не тратил ресурсы на поиск несуществующих объектов.

← На главную