Почему не работают поля поиска при переносе данных из 1С 7.7 в 1С 8?

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

При переносе данных между базами 1С:Предприятие 7.7 и 1С:Предприятие 8 с помощью конфигурации 1С:Конвертация данных 2.1 разработчики часто сталкиваются с ситуацией, когда стандартный поиск по полям поиска не находит существующие объекты в базе-приемнике и создает дубли. Разберем, как именно функционирует данный механизм, почему при выгрузке из 7.7 поиск по полям работает так же, как и между базами восьмой версии, и в чем заключается ключевая ошибка при написании кода в обработчике Поля поиска.

Механика работы обработчика «Поля поиска»

Проанализируем алгоритм, по которому платформа выполняет сопоставление объектов в базе-приемнике при загрузке данных:

  1. Обработчик Поля поиска вызывается платформой в цикле. При первом входе в событие переменная НомерВариантаПоиска всегда инициализируется значением 1.
  2. Если в коде обработчика переменной СтрокаИменСвойствПоиска присваивается список реквизитов через запятую, платформа выполняет поиск элемента по этим свойствам.
  3. Если объект успешно найден, поиск завершается, и ссылка сопоставляется.
  4. Если объект не найден, платформа автоматически инкрементирует переменную НомерВариантаПоиска на 1 (становится равной 2) и повторно вызывает обработчик Поля поиска.
  5. Итерации продолжаются до тех пор, пока объект не будет найден, либо пока СтрокаИменСвойствПоиска не останется пустой, либо пока переменной ПрекратитьПоиск не будет присвоено значение Истина.

Важно отметить: платформа базы-источника не имеет значения. Будь то выгрузка из 1С 7.7 или из 1С 8, поиск по полям осуществляется непосредственно в базе-приемнике (1С 8) по переданным в XML значениям реквизитов.

В чем заключалась ошибка автора

Посмотрим на исходный фрагмент кода, где была допущена логическая ошибка:


Если СвойстваПоиска["ЭтоГруппа"] Тогда
    Если НомерВариантаПоиска = 1 тогда
        СтрокаИменСвойствПоиска = "Код, Наименование, Родитель, ЭтоГруппа";
    ИначеЕсли НомерВариантаПоиска = 2 тогда
        СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
    КонецЕсли;
Иначе
    Если ЗначениеЗаполнено(СвойстваПоиска["Артикул"]) Тогда
        Если НомерВариантаПоиска = 3 тогда // Ошибка: на первой итерации для элемента НомерВариантаПоиска равен 1, а не 3!
            СтрокаИменСвойствПоиска = "Артикул, Код, Наименование, Родитель, ЭтоГруппа";
        ИначеЕсли НомерВариантаПоиска = 4 тогда
            СтрокаИменСвойствПоиска = "Артикул, Наименование, Родитель, ЭтоГруппа";
        ...

Выясним причину сбоя: когда загружается обычный элемент справочника (не группа), срабатывает ветка Иначе. На первой итерации значение переменной НомерВариантаПоиска равно 1. Однако условия проверяют значения 3, 4, 5, 6, 7. В результате переменная СтрокаИменСвойствПоиска остается пустой (Неопределено), платформа считает, что варианты поиска исчерпаны, прерывает сопоставление и создает новый элемент.

Правильная организация условий в обработчике «Поля поиска»

Разберем по шагам, как исправить код. В каждой независимой ветке условий нумерация вариантов поиска должна начинаться строго с 1.


Если СвойстваПоиска["ЭтоГруппа"] Тогда
    Если НомерВариантаПоиска = 1 Тогда
        СтрокаИменСвойствПоиска = "Код, Наименование, Родитель, ЭтоГруппа";
    ИначеЕсли НомерВариантаПоиска = 2 Тогда
        СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
    КонецЕсли;
Иначе
    Если ЗначениеЗаполнено(СвойстваПоиска["Артикул"]) Тогда
        Если НомерВариантаПоиска = 1 Тогда
            СтрокаИменСвойствПоиска = "Артикул, Код, Наименование, Родитель, ЭтоГруппа";
        ИначеЕсли НомерВариантаПоиска = 2 Тогда
            СтрокаИменСвойствПоиска = "Артикул, Наименование, Родитель, ЭтоГруппа";
        ИначеЕсли НомерВариантаПоиска = 3 Тогда
            СтрокаИменСвойствПоиска = "Код, Наименование, Родитель, ЭтоГруппа";
        ИначеЕсли НомерВариантаПоиска = 4 Тогда
            СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
        КонецЕсли;
    Иначе
        Если НомерВариантаПоиска = 1 Тогда
            СтрокаИменСвойствПоиска = "Код, Наименование, Родитель, ЭтоГруппа";
        ИначеЕсли НомерВариантаПоиска = 2 Тогда
            СтрокаИменСвойствПоиска = "Наименование, Родитель, ЭтоГруппа";
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Дополнительные факторы, мешающие поиску объектов

Если структура условий выстроена правильно, но сопоставление все равно не происходит, проанализируем типовые проблемы совместимости между 1С 7.7 и 1С 8:

  1. Различия в формате реквизита Код: В 1С 7.7 длина кода может быть меньше или больше, чем в 1С 8, а также могут отсутствовать лидирующие нули (например, код "12" в 7.7 и "000000012" в 8.3). Поиск по точному совпадению строк в таком случае не сработает. Перед поиском можно нормализовать код прямо в структуре СвойстваПоиска.
  2. Поиск по реквизиту Родитель: Если родительский элемент еще не был загружен и сопоставлен на момент поиска подчиненного элемента, поиск с участием поля Родитель завершится неудачей.
  3. Флаги поиска в ПКС: Поля, указанные в переменной СтрокаИменСвойствПоиска, обязательно должны быть выгружены в коллекцию СвойстваПоиска (в правилах конвертации свойств должен стоять флаг поиска).

Альтернативное решение: прямой поиск запросом

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Артикул = &Артикул
    |	И Номенклатура.ЭтоГруппа = &ЭтоГруппа";

Запрос.УстановитьПараметр("Артикул", СвойстваПоиска["Артикул"]);
Запрос.УстановитьПараметр("ЭтоГруппа", СвойстваПоиска["ЭтоГруппа"]);

Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
    СсылкаНаОбъект = Выборка.Ссылка;
КонецЕсли;

ПрекратитьПоиск = Истина;

В этом случае мы явно присваиваем найденную ссылку переменной СсылкаНаОбъект и устанавливаем ПрекратитьПоиск = Истина, что полностью исключает зависимость от переменной НомерВариантаПоиска.

← На главную