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