При написании обработок загрузки данных из внешних файлов Excel начинающие разработчики часто сталкиваются с ситуацией: в файле содержится тысяча строк, обработка выполняется без видимых ошибок, однако в результате в справочнике оказывается всего одна запись — самая последняя из файла.
Разберем по шагам, почему возникает эта проблема, проанализируем ошибки в исходном коде и рассмотрим правильный способ создания новых объектов и подчиненных элементов в 1С.
Рассмотрим стандартную логику, из-за которой возникает подобное поведение:
ПолучитьОбъект() для результатов выборки.Главная ошибка заключается в том, что метод ПолучитьОбъект() предназначен исключительно для считывания и изменения уже существующих в базе данных элементов. Если справочник изначально пустой или запрос возвращает ссылку на ранее записанный объект, вызов ПолучитьОбъект() не создает новую запись, а считывает имеющийся элемент и перезаписывает его реквизиты новыми данными из очередной строки Excel.
Для добавления новой записи в справочник платформы 1С необходимо использовать метод СоздатьЭлемент() объекта менеджер справочника. Посмотрим на примере, как должен выглядеть цикл загрузки данных без использования лишних запросов:
Для Каждого Стр Из ТЗКонтрагентов Цикл
// Создаем новый элемент справочника моделей
НоваяМодель = Справочники.асМодели.СоздатьЭлемент();
НоваяМодель.Наименование = Стр.Марка + " " + Стр.Модель + " " + Стр.Поколение;
НоваяМодель.НаименованиеПолное = Стр.Марка + " " + Стр.Модель + " " + Стр.Поколение + " (" + Стр.Годот + "-" + Стр.ГодДо + ")";
Попытка
НоваяМодель.Записать();
Исключение
Сообщить("Не удалось записать модель: " + ОписаниеОшибки());
Продолжить;
КонецПопытки;
// Создаем подчиненный элемент (комплектацию)
НоваяКомплектация = Справочники.асВариантыКомплектации.СоздатьЭлемент();
НоваяКомплектация.Наименование = Стр.Модификация + " кузов " + Стр.Серия;
НоваяКомплектация.НаименованиеПолное = Стр.Модификация + " (" + Стр.Годот + "-" + Стр.ГодДо + ") кузов " + Стр.Серия;
// Владельцем назначаем ссылку только что записанной модели
НоваяКомплектация.Владелец = НоваяМодель.Ссылка;
Попытка
НоваяКомплектация.Записать();
Исключение
Сообщить("Не удалось записать комплектацию: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
При реализации загрузки следует обратить внимание на несколько ключевых моментов:
Владелец, если родительский объект еще не записан в базу данных. Вызов метода Записать() для родительского элемента формирует ссылку НоваяМодель.Ссылка, которая затем успешно передается подчиненному элементу.СоздатьЭлемент() приведет к дублированию записей. В реальных задачах перед созданием нового элемента рекомендуется проверять его наличие в базе с помощью методов НайтиПоНаименованию(), НайтиПоРеквизиту() или посредством запроса.Использование COM-объекта Excel.Application имеет ряд существенных ограничений: требуется наличие установленного MS Excel на рабочем месте, код не работает на серверах под управлением Linux и медленно обрабатывает большие объемы данных. Для более надежной и быстрой загрузки рекомендуется использовать встроенный объект ТабличныйДокумент:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(Объект.ВыборФайла);
Исключение
Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Проход по строкам табличного документа
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
ТекстЯчейки = ТабДок.ПолучитьОбласть(НомерСтроки, 1).ТекущаяОбласть.Текст;
// Логика заполнения и создания элементов
КонецЦикла;
Метод ТабличныйДокумент.Прочитать() работает кроссплатформенно, быстро считывает файлы форматов .xls, .xlsx и .ods, а также не оставляет зависших процессов в оперативной памяти компьютера.