При интеграции систем или выгрузке данных из конфигураций на платформе 1С:Предприятие 7.7 в 1С:Предприятие 8 через COM-соединение разработчики часто сталкиваются с ситуацией, когда стандартный метод поиска контрагента по реквизиту ИНН не дает результатов. Проанализируем типичный пример: в базе-источнике значение реквизита хранится в виде 7202131440/720201001, а из внешней системы для поиска передается только десятизначный или двенадцатизначный ИНН (например, 7202131440).
Попытка использовать метод НайтиПоРеквизиту терпит неудачу:
КонтрагентСОМ = V77.CreateObject("Справочник.Контрагенты");
Строкаинн = Объект.ИНН;
Если КонтрагентСОМ.НайтиПоРеквизиту("ИНН", Строкаинн) = 1 Тогда
Объект.Заказчик2 = КонтрагентСОМ.Наименование;
Иначе
Сообщить("Контрагента с таким ИНН нет в базе!");
КонецЕсли;
Выясним причину такого поведения платформы и подробно разберем все работающие способы решения этой задачи.
Рассмотрим особенности платформы 1С:Предприятие 7.7, приводящие к данной проблеме:
НайтиПоРеквизиту выполняет поиск исключительно на точное равенство значений. Использование масок поиска или подстановочных символов (таких как *, ? или %) синтаксисом платформы 7.7 не предусмотрено. Значение 7202131440 никогда не будет признано равным строке 7202131440/720201001.ИНН проектировался под совместное хранение связки «ИНН/КПП» длиной до 20–22 знаков.Штатный механизм запросов 1С 7.7 («черный запрос») не поддерживает оператор ПОДОБНО, однако секция Условие позволяет использовать встроенные функции работы со строками, такие как Лев, Найти или СокрЛП. Это позволяет выполнить поиск по префиксу строки прямо на стороне базы 7.7 через COM-объект.
Разберем по шагам реализацию этого подхода:
ЗапросCOM = V77.CreateObject("Запрос");
СтрокаИНН = СокрЛП(Объект.ИНН);
ДлинаИНН = СтрДлина(СтрокаИНН);
ТекстЗапроса =
"//{{ЗАПРОС(ПоискПоИНН)
|Текущий = Справочник.Контрагенты.ТекущийЭлемент;
|ИНН = Справочник.Контрагенты.ИНН;
|Группировка Текущий без групп;
|Условие (Лев(СокрЛП(ИНН), " + ДлинаИНН + ") = """ + СтрокаИНН + """);
|"//}}ЗАПРОС
;
Если ЗапросCOM.Выполнить(ТекстЗапроса) = 1 Тогда
Если ЗапросCOM.Группировка(1) = 1 Тогда
Объект.Заказчик2 = ЗапросCOM.Текущий.Наименование;
Иначе
Сообщить("Контрагент с ИНН " + СтрокаИНН + " не найден в базе 7.7!");
КонецЕсли;
Иначе
Сообщить("Ошибка выполнения запроса к базе 7.7!");
КонецЕсли;
Обратите внимание: у одной организации может быть несколько обособленных подразделений с одинаковым ИНН, но разными КПП. В этом случае группировка запроса вернет несколько строк. При необходимости можно обойти все найденные записи в цикле Пока ЗапросCOM.Группировка(1) = 1 Цикл и выбрать нужный филиал либо головную организацию.
Если справочник контрагентов содержит сравнительно небольшое число записей (до нескольких тысяч) и запрос строить не требуется, можно использовать штатный перебор элементов с проверкой вхождения ИНН. Для оптимизации скорости обязательно отключаем выборку групп, передавая параметр 0 в метод ВыбратьЭлементы.
Посмотрим на пример кода:
КонтрагентСОМ = V77.CreateObject("Справочник.Контрагенты");
СтрокаИНН = СокрЛП(Объект.ИНН);
ДлинаИНН = СтрДлина(СтрокаИНН);
Найден = Ложь;
КонтрагентСОМ.ВыбратьЭлементы(0);
Пока КонтрагентСОМ.ПолучитьЭлемент() = 1 Цикл
ТекущийИНН = СокрЛП(КонтрагентСОМ.ИНН);
Если Лев(ТекущийИНН, ДлинаИНН) = СтрокаИНН Тогда
Объект.Заказчик2 = КонтрагентСОМ.Наименование;
Найден = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не Найден Тогда
Сообщить("Контрагент с ИНН " + СтрокаИНН + " не найден!");
КонецЕсли;
Если информационная база 1С 7.7 работает под управлением Microsoft SQL Server, наиболее производительным решением будет выполнение прямого запроса через объект ADODB.Connection в обход COM-соединения с самой 1С. В этом случае используется стандартный оператор LIKE.
План реализации:
1cv7.dd) идентификатор таблицы справочника контрагентов (например, SC123) и идентификатор поля ИНН (например, SP125).WHERE SP125 LIKE '7202131440%' AND ISMARK = 0.Если конфигурация 7.7 доступна для изменения, проанализируем архитектурное решение:
Контрагенты новый реквизит ЧистыйИНН (тип «Строка», длина 12) и устанавливаем для него признак Сортировка.ИНН по символу / и записывает первую часть в созданный реквизит.ЧистыйИНН.КонтрагентСОМ.НайтиПоРеквизиту("ЧистыйИНН", Строкаинн) будет отрабатывать мгновенно по индексу.Если постоянное динамическое обращение к 7.7 замедляет работу пользователей, целесообразно загрузить справочник контрагентов из базы 7.7 в базу 8 целиком (в промежуточную таблицу значений или отдельный служебный справочник). При загрузке строка ИНН разделяется на чистый ИНН и КПП с помощью функции СтрРазделить (или Найти), после чего дальнейший поиск и сопоставление выполняются средствами запросов платформы «1С:Предприятие 8», где полноценно поддерживаются конструкции ПОДОБНО и индексированный поиск по реквизитам.