Как исправить ошибку «Поле объекта не обнаружено» при ручном поиске в 1С:Конвертация данных 2.1?

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

При настройке правил обмена в инструменте «1С:Конвертация данных 2.1» (КД 2.1) разработчики часто сталкиваются с необходимостью реализовать нетривиальную логику сопоставления объектов базы-источника и базы-приемника. Стандартного поиска по уникальному идентификатору (GUID) или равенству кодов/наименований бывает недостаточно. В таких случаях мы прибегаем к написанию произвольного кода в обработчике «Поля поиска» на уровне Правил конвертации объектов (ПКО).

Однако при написании кода «вслепую» прямо в интерфейсе Конвертации данных легко допустить синтаксическую ошибку, которая проявит себя только на этапе загрузки данных в базу-приемник. Одной из самых коварных и распространенных ошибок является сообщение: Ошибка в обработчике события ПоследовательностьПолейПоиска... ОписаниеОшибки = Поле объекта не обнаружено (Наименование). Давайте детально разберем, почему возникает эта ошибка, как правильно работать с коллекциями в КД 2.1 и как настроить полноценную отладку, чтобы больше не совершать подобных промахов.

Выясняем причину: Структура против Соответствия

Давайте проанализируем исходный код, который вызвал ошибку у автора темы. В обработчике «Поля поиска» выполнялся следующий запрос:


Запрос.УстановитьПараметр("Наименование", Лев(СвойстваПоиска.Наименование, 3) + "%");

На первый взгляд код выглядит абсолютно логичным. Мы пытаемся получить значение переданного для поиска наименования, взять его первые три символа и использовать в качестве параметра запроса с оператором ПОДОБНО. Однако платформа 1С на этом шаге аварийно завершает работу с ошибкой обращения к несуществующему полю объекта.

В чем же кроется секрет? Всё дело в типе данных переменной СвойстваПоиска. В КД 2.1 эта переменная является объектом типа Соответствие (Map), а не Структура (Structure).

В платформе «1С:Предприятие» работа с этими коллекциями различается кардинальным образом:

  1. Структура позволяет обращаться к своим свойствам «через точку» (например, Структура.ИмяСвойства), так как ключи структуры гарантированно являются строками и соответствуют правилам образования идентификаторов.
  2. Соответствие хранит пары «Ключ-Значение», где ключом может выступать абсолютно любой тип данных. Из-за этой универсальности платформа запрещает обращение к элементам соответствия через точку. Допускается обращение только с помощью квадратных скобок или специального метода.

Таким образом, попытка написать СвойстваПоиска.Наименование неизбежно приводит к ошибке Поле объекта не обнаружено, так как у самого объекта Соответствие нет такого встроенного свойства.

Решение проблемы: Правильный синтаксис работы со СвойствамиПоиска

Чтобы исправить эту ошибку, нам необходимо изменить способ обращения к элементам коллекции. Мы можем сделать это двумя способами:

Способ 1. Использование квадратных скобок (рекомендуемый):

ИскомоеЗначение = СвойстваПоиска["Наименование"];

Способ 2. Использование метода Получить():

ИскомоеЗначение = СвойстваПоиска.Получить("Наименование");

Оба варианта абсолютно равноправны и безопасны. Если мы перепишем строку установки параметра запроса из примера автора, она примет следующий вид:


Запрос.УстановитьПараметр("Наименование", Лев(СвойстваПоиска["Наименование"], 3) + "%");

После такого простого изменения ошибка обращения к свойству исчезнет.

Анализируем работу с пустым источником в ПКС

В описании проблемы автора есть еще один важный нюанс: «В ПКС в источнике пусто, в приемнике Наименование... В обработчике стоит Значение = Источник;».

Давайте разберем, к чему приводит такая конструкция:

Если вам необходимо передать конкретное строковое значение в приемник при пустом источнике, следует писать явное присвоение в обработчике ПКС «Перед выгрузкой»:


Значение = "Значение по умолчанию"; // Или любой другой ваш алгоритм получения строки

Если же данные для поиска вообще не связаны напрямую с реквизитами создаваемого объекта-приемника, использовать для этого ПКС реквизита Наименование — не лучшая практика. Для таких целей в КД 2.1 предусмотрен механизм параметров объектов.

Использование параметров объекта для гибкого поиска

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

  1. Откройте ваше ПКО и перейдите на вкладку «Параметры».
  2. Добавьте новый параметр, например, СтрокаДляПоиска.
  3. В ПКС для этого параметра укажите галочки «Передавать в параметр» и «Поиск».
  4. Заполните значение параметра в источнике (в обработчике ПКС «Перед выгрузкой» или «При выгрузке»).
  5. В обработчике ПКО «Поля поиска» в базе-приемнике обратитесь к этому параметру через специальное соответствие ПараметрыОбъекта:

// ПараметрыОбъекта — это тоже Соответствие, обращаемся через квадратные скобки
ИскомыйТекст = ПараметрыОбъекта["СтрокаДляПоиска"];

Шаблон правильного ручного поиска в КД 2.1

Давайте соберем воедино все лучшие практики и напишем надежный, отказоустойчивый шаблон для реализации ручного поиска в обработчике ПКО «Поля поиска». Нам нужно не только написать правильный запрос, но и корректно управлять логикой поиска КД с помощью предопределенных переменных.

Разберем основные переменные, которыми мы должны управлять:

Посмотрим на пример готового шаблона кода:


// 1. Проверяем, заполнено ли свойство для поиска в пришедших данных
НаименованиеДляПоиска = СвойстваПоиска["Наименование"];

Если ЗначениеЗаполнено(НаименованиеДляПоиска) Тогда

    // Берем первые 3 символа для поиска по маске
    СтрокаМаски = Лев(СокрЛП(НаименованиеДляПоиска), 3);
    
    Если СтрДлина(СтрокаМаски) >= 3 Тогда
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |	ТарифныеСетки.Ссылка КАК Ссылка,
            |	ТарифныеСетки.Наименование КАК Наименование
            |ИЗ
            |	Справочник.ТарифныеСетки КАК ТарифныеСетки
            |ГДЕ
            |	ТарифныеСетки.Наименование ПОДОБНО &Маска";
            
        Запрос.УстановитьПараметр("Маска", СтрокаМаски + "%");
        
        РезультатЗапроса = Запрос.Выполнить();
        
        Если Не РезультатЗапроса.Пустой() Тогда
            
            Выборка = РезультатЗапроса.Выбрать();
            Пока Выборка.Следующий() Цикл
                
                // Дополнительная проверка на формат наименования (например, четвертый символ должен быть пробелом)
                Если Сред(Выборка.Наименование, 4, 1) <> " " Тогда
                    Продолжить;
                КонецЕсли;
                
                // Если нашли подходящий элемент — фиксируем ссылку
                СсылкаНаОбъект = Выборка.Ссылка;
                Прервать;
                
            КонецЦикла;
            
        КонецЕсли;

    КонецЕсли;

КонецЕсли;

// 2. Управляем поведением КД после завершения нашего поиска
Если ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
    
    // Объект успешно найден в базе-приемнике. Останавливаем дальнейший поиск.
    ПрекратитьПоиск = Истина;
    
    // Запрещаем КД затирать оригинальные реквизиты найденного объекта нашими поисковыми значениями
    УстанавливатьУОбъектаВсеСвойстваПоиска = Ложь;
    
Иначе
    
    // Если объект не найден, мы можем либо разрешить КД продолжить стандартный поиск,
    // либо принудительно прекратить поиск, что приведет к созданию НОВОГО объекта.
    // ПрекратитьПоиск = Истина; // Раскомментируйте, если создание нового объекта обязательно при неудаче ручного поиска

КонецЕсли;

Как настроить отладку обработчиков и забыть про ошибки «вслепую»

Написание кода в текстовых полях Конвертации данных без возможности поставить точку останова и посмотреть значения переменных — это тяжелый путь, ведущий к множеству скрытых дефектов. На самом деле в КД 2.1 встроен мощный штатный механизм отладки, которым пользуются все профессиональные разработчики.

Давайте разберем по шагам, как запустить отладку вашего кода в обработчике «Поля поиска»:

  1. Выгрузка кода обработчиков в файл:

    В базе Конвертации данных перейдите в меню настройки правил обмена. Нажмите на кнопку «Выгрузить код обработчиков». Система предложит вам сохранить текстовый файл (например, Handlers.txt). Сохраните его на свой компьютер.

  2. Создание модуля отладки:

    В комплекте поставки КД 2.1 идет специальная внешняя обработка отладки (обычно она называется УниверсальныйОбменДаннымиXML_Отладка.epf). Откройте конфигуратор вашей базы-приемника, создайте новую внешнюю обработку, скопируйте туда модуль из шаблона отладки и загрузите в него ваш сгенерированный файл Handlers.txt. Платформа создаст полноценные процедуры для каждого вашего обработчика.

  3. Подключение отладки при загрузке:

    Запустите базу-приемник в режиме 1С:Предприятие с включенным режимом отладки. Откройте обработку УниверсальныйОбменДаннымиXML. На вкладке «Параметры отладки» установите галочку «Включить режим отладки обработчиков загрузки» и укажите путь к созданной внешней обработке сгенерированного кода.

  4. Установка точек останова:

    Вернитесь в конфигуратор базы-приемника. Найдите в модуле внешней обработки процедуру, отвечающую за поиск вашего объекта (она будет называться примерно так: ПКО_ПоляПоиска_...). Поставьте на строчку с вашим запросом стандартную точку останова клавишей F9.

  5. Запуск обмена:

    Начните загрузку данных в обработке обмена. Выполнение программы мгновенно остановится в конфигураторе на вашей точке останова. Теперь вы можете нажать Shift+F9 (Табло) и в реальном времени посмотреть содержимое переменных СвойстваПоиска, ПараметрыОбъекта, проверить результат выполнения запроса и пошагово отследить всю логику работы вашего алгоритма.

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

← На главную