Как настроить загрузку номенклатуры и характеристик из табличного документа в 1С без создания дублей?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Управленческий учет Торговля и дистрибуция
← На главную

При импорте данных из Excel или других табличных документов с помощью стандартной обработки «Загрузка данных из табличного документа» часто возникает задача: необходимо загрузить позиции в табличную часть документа, но при этом избежать создания дубликатов элементов справочников. Рассмотрим, как правильно организовать загрузку номенклатуры и характеристик, если часть элементов уже существует в информационной базе, а часть — поступает впервые.

Причина возникновения дублей и особенности работы обработки

Проанализируем механику работы стандартной обработки. В режиме загрузки в табличную часть документа установка режима сопоставления «Искать» выполняет лишь поиск уже имеющихся ссылок. Если элемент не найден в справочнике, обработка в этом режиме не создаст новый объект автоматически, а оставит поле пустым. Если же выбран режим «Загружать», то при повторном запуске обработки система создаст дублирующие записи.

Отдельное внимание стоит обратить на справочник ХарактеристикиНоменклатуры. Этот справочник является подчиненным (владельцем выступает конкретный элемент номенклатуры или вид номенклатуры). Поэтому поиск и создание характеристик должны выполняться строго с учетом ссылки на владельца.

Решение 1. Использование режима «Вычислить» для поиска и создания объектов

Выясним, как настроить программное выражение в режиме загрузки «Вычислить». Данный режим позволяет написать произвольный алгоритм на языке 1С, который выполняет поиск элемента в базе и, если объект отсутствует, программно создает его и возвращает ссылку в переменную Результат.

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


Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Артикул = &Артикул");
Запрос.УстановитьПараметр("Артикул", ТекстыЯчеек[2]);
РезультатЗапроса = Запрос.Выполнить();

Если РезультатЗапроса.Пустой() Тогда
    НайденнаяЕдиницаОбъект = Справочники.Номенклатура.СоздатьЭлемент();
    НайденнаяЕдиницаОбъект.Наименование = ТекстыЯчеек[1];
    НайденнаяЕдиницаОбъект.Артикул = ТекстыЯчеек[2];
    НайденнаяЕдиницаОбъект.СтавкаНДС = Перечисления.СтавкиНДС.НДС18;
    НайденнаяЕдиницаОбъект.ЕдиницаИзмерения = Справочники.БазовыеЕдиницыИзмерения.НайтиПоНаименованию("шт");
    НайденнаяЕдиницаОбъект.ВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоНаименованию("Ювелирное изделие");
    
    Попытка
        НайденнаяЕдиницаОбъект.Записать();
        Результат = НайденнаяЕдиницаОбъект.Ссылка;
    Исключение
        Сообщить("Не удалось записать номенклатуру: " + ОписаниеОшибки());
    КонецПопытки;
Иначе
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    Результат = Выборка.Ссылка;
КонецЕсли;

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


// Сначала получаем ссылку на владельца (Номенклатуру)
СсылкаНоменклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", ТекстыЯчеек[2]);

Если ЗначениеЗаполнено(СсылкаНоменклатура) Тогда
    Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.ХарактеристикиНоменклатуры ГДЕ Владелец = &Владелец И Наименование = &Наименование");
    Запрос.УстановитьПараметр("Владелец", СсылкаНоменклатура);
    Запрос.УстановитьПараметр("Наименование", ТекстыЯчеек[3]);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если РезультатЗапроса.Пустой() Тогда
        ХарактеристикаОбъект = Справочники.ХарактеристикиНоменклатуры.СоздатьЭлемент();
        ХарактеристикаОбъект.Владелец = СсылкаНоменклатура;
        ХарактеристикаОбъект.Наименование = ТекстыЯчеек[3];
        
        Попытка
            ХарактеристикаОбъект.Записать();
            Результат = ХарактеристикаОбъект.Ссылка;
        Исключение
            Сообщить("Не удалось записать характеристику: " + ОписаниеОшибки());
        КонецПопытки;
    Иначе
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Результат = Выборка.Ссылка;
    КонецЕсли;
КонецЕсли;

Решение 2. Двухэтапная загрузка (рекомендуемый подход)

Рассмотренный выше метод с выполнением запроса на каждую строку файла хорошо подходит для небольших таблиц. Однако при импорте тысяч строк выполнение запросов в цикле может существенно замедлить процесс. В таких случаях эффективнее использовать двухэтапный порядок загрузки:

  1. Этап 1: Загрузка в справочники. Переключим обработку в режим «Загрузка в справочник». Сначала запустим импорт для справочника Номенклатура, установив ключевым полем поиска Артикул. После этого запустим импорт для справочника ХарактеристикиНоменклатуры, выбрав поиск по наименованию и владельцу. Обработка самостоятельно сопоставит имеющиеся позиции и создаст отсутствующие.
  2. Этап 2: Загрузка в документ. Переключим обработку в режим «Загрузка в табличную часть» целевого документа (например, ПоступлениеТоваров). Для реквизитов Номенклатура и Характеристика установим режим сопоставления «Искать». Так как все элементы уже гарантированно созданы на первом этапе, документ заполнится быстро и без дублей.

Важные рекомендации при подготовке загрузки

Проанализируем технические нюансы, которые следует учитывать при использовании пользовательских скриптов:

  1. Завязка на индексы ячеек: Использование жесткой индексации видов ТекстыЯчеек[2] требует строгого контроля порядка колонок в файле поставщика. При изменении структуры столбцов код запишет некорректные данные.
  2. Заполнение обязательных реквизитов: При создании элементов справочников через метод СоздатьЭлемент() обязательно заполняйте все реквизиты, необходимые для логики вашей конфигурации (базовая единица измерения, вид номенклатуры, ставка НДС).
  3. Альтернативные механизмы: В современных конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) рекомендуется использовать встроенный мастер «Загрузка данных из файла», который умеет сопоставлять ненайденные позиции в интерактивном режиме без необходимости написания программного кода.
← На главную