При переносе данных между базами 1С:Предприятие 7.7 и 1С:Предприятие 8 с помощью конфигурации 1С:Конвертация данных 2.1 разработчики часто сталкиваются с ситуацией, когда стандартный поиск по полям поиска не находит существующие объекты в базе-приемнике и создает дубли. Разберем, как именно функционирует данный механизм, почему при выгрузке из 7.7 поиск по полям работает так же, как и между базами восьмой версии, и в чем заключается ключевая ошибка при написании кода в обработчике Поля поиска.
Проанализируем алгоритм, по которому платформа выполняет сопоставление объектов в базе-приемнике при загрузке данных:
НомерВариантаПоиска всегда инициализируется значением 1.СтрокаИменСвойствПоиска присваивается список реквизитов через запятую, платформа выполняет поиск элемента по этим свойствам.НомерВариантаПоиска на 1 (становится равной 2) и повторно вызывает обработчик Поля поиска.СтрокаИменСвойствПоиска не останется пустой, либо пока переменной ПрекратитьПоиск не будет присвоено значение Истина.Важно отметить: платформа базы-источника не имеет значения. Будь то выгрузка из 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С 7.7 длина кода может быть меньше или больше, чем в 1С 8, а также могут отсутствовать лидирующие нули (например, код "12" в 7.7 и "000000012" в 8.3). Поиск по точному совпадению строк в таком случае не сработает. Перед поиском можно нормализовать код прямо в структуре СвойстваПоиска.Родитель: Если родительский элемент еще не был загружен и сопоставлен на момент поиска подчиненного элемента, поиск с участием поля Родитель завершится неудачей.СтрокаИменСвойствПоиска, обязательно должны быть выгружены в коллекцию СвойстваПоиска (в правилах конвертации свойств должен стоять флаг поиска).Когда стандартных вариантов поиска недостаточно (например, требуется очистка от пробелов через СокрЛП, поиск без учета регистра или сопоставление по сложным условиям), рекомендуется выполнять прямой запрос к базе данных внутри обработчика Поля поиска:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул
| И Номенклатура.ЭтоГруппа = &ЭтоГруппа";
Запрос.УстановитьПараметр("Артикул", СвойстваПоиска["Артикул"]);
Запрос.УстановитьПараметр("ЭтоГруппа", СвойстваПоиска["ЭтоГруппа"]);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаОбъект = Выборка.Ссылка;
КонецЕсли;
ПрекратитьПоиск = Истина;
В этом случае мы явно присваиваем найденную ссылку переменной СсылкаНаОбъект и устанавливаем ПрекратитьПоиск = Истина, что полностью исключает зависимость от переменной НомерВариантаПоиска.