Загрузка данных из внешних файлов Excel в справочники 1С — одна из самых частых задач программиста. Однако на практике разработчики часто сталкиваются с двумя проблемами: созданием дублей (когда система не «узнает» уже существующий товар) и необходимостью соблюдения специфических правил нумерации. В этой статье мы подробно разберем, как правильно организовать поиск объектов, оптимизировать производительность и настроить коды справочника так, как этого требует бизнес-логика.
Рассмотрим ситуацию: при создании новой карточки номенклатуры программно формируется наименование, состоящее из базового названия и модели (например, «Ковер Персидский» + «Модель А»). Ошибка часто кроется в том, что поиск существующего элемента выполняется только по базовому названию, а запись — по расширенному. В результате 1С не находит соответствия и создает новую запись при каждой загрузке.
Проанализируем фрагмент кода, где выполняется поиск и запись:
// Неправильный подход: ищем по короткому имени, записываем длинное
НайтиНаименованиеСпрТовары = СпрТовары.НайтиПоНаименованию(НаименованиеТовара, Истина);
Если НайтиНаименованиеСпрТовары = СпрТовары.ПустаяСсылка Тогда
НовЭл = СпрТовары.СоздатьЭлемент();
НовЭл.Наименование = НаименованиеТовара + " " + МодельТовара;
НовЭл.Записать();
КонецЕсли;
Чтобы система корректно определяла уже созданный товар, необходимо обеспечить полное соответствие строки поиска строке записи. Исправленный алгоритм должен выглядеть следующим образом:
// Правильный подход: ищем по тому же шаблону, по которому записываем
СтрокаПоиска = СокрЛП(НаименованиеТовара) + " " + СокрЛП(МодельТовара);
НайтиНаименованиеСпрТовары = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаПоиска, Истина);
Если НайтиНаименованиеСпрТовары.Пустая() Тогда
НовЭл = Справочники.Номенклатура.СоздатьЭлемент();
НовЭл.Наименование = СтрокаПоиска;
// ... заполнение других реквизитов ...
НовЭл.Записать();
КонецЕсли;
Важно помнить, что функция СокрЛП критически важна при работе с Excel, так как в ячейках часто содержатся невидимые пробелы в начале или конце строки, которые сделают поиск по наименованию безрезультатным.
Иногда требования заказчика выходят за рамки стандартного автонумератора 1С. Например, нужно, чтобы код всей новой номенклатуры начинался с цифры «2». В системе 1С код присваивается в момент записи объекта. Чтобы изменить его, мы можем выполнить перезапись сразу после создания.
Разберем по шагам, как это реализовать в процедуре создания:
Записать(), чтобы система выделила следующий номер по порядку.Пример кода:
НовЭл.Наименование = НаименованиеТоваров + " " + МодельТовара;
НовЭл.Записать(); // Здесь получаем стандартный код, например "000001"
// Меняем первую цифру на 2
НовЭл.Код = "2" + Сред(НовЭл.Код, 2);
НовЭл.Записать(); // Сохраняем изменения
Важное замечание: Такой подход допустим при разовых загрузках, но для постоянной работы лучше использовать событие ПриУстановкеНовогоКода в модуле объекта справочника Номенклатура. Это позволит избежать двойной записи в базу данных и повысит надежность системы.
В представленном в начале статьи коде процедура ЗаписатьНовыйТовар вызывается внутри цикла на стороне клиента. Это приводит к так называемым «клиент-серверным прыжкам». Если в вашем файле 1000 строк, компьютер 1000 раз обратится к серверу, что существенно замедлит загрузку.
Рассмотрим, как оптимизировать этот процесс:
ТаблицаЗначений или Массив структур.Проанализируем преимущества использования транзакций с помощью НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Если при загрузке 500-й строки произойдет ошибка (например, выключится свет или пропадет сеть), без транзакции в базе останется «мусор» из первых 499 строк. С транзакцией система просто откатит все изменения к исходному состоянию.
Метод Новый COMОбъект("Excel.Application") медленный и требует наличия установленного Microsoft Office на сервере или компьютере пользователя. Современная платформа 1С позволяет читать файлы Excel гораздо эффективнее.
Выясним, как использовать ТабличныйДокумент для этих целей:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
КоличествоСтрок = ТабДок.ВысотаТаблицы;
Для Сч = 2 По КоличествоСтрок Цикл
Наименование = ТабДок.Область(Сч, 1).Текст;
// ... логика обработки ...
КонецЦикла;
Этот способ работает в разы быстрее, стабильнее и не зависит от стороннего ПО.
Рассмотрим еще одну тонкость. Если в вашем Excel-файле одна и та же новая позиция встречается дважды, метод НайтиПоНаименованию во втором цикле может ее не найти, если данные еще не были окончательно зафиксированы в индексе базы данных (актуально для некоторых режимов работы).
Для решения этой проблемы рекомендуется создать временное Соответствие на сервере, где ключом будет наименование, а значением — ссылка на созданный объект. Перед поиском в базе данных сначала проверяйте наличие товара в этом «кеше» памяти.
Резюме: Для создания качественной загрузки номенклатуры всегда используйте СокрЛП, выполняйте поиск по тому же шаблону, по которому пишете наименование, старайтесь избегать COM-объектов в пользу встроенных средств платформы и всегда группируйте серверные вызовы для ускорения работы программы.