Почему при загрузке данных из Excel в 1С записывается только одна строка и как это исправить?

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

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

Разберем по шагам, почему возникает эта проблема, проанализируем ошибки в исходном коде и рассмотрим правильный способ создания новых объектов и подчиненных элементов в 1С.

Выясним причину ошибки в логике обработки

Рассмотрим стандартную логику, из-за которой возникает подобное поведение:

  1. Обработка считывает данные из таблицы Excel и загружает их во временную таблицу значений.
  2. Далее запускается цикл обхода строк таблицы значений.
  3. Внутри цикла выполняется запрос к справочнику и предпринимается попытка вызвать метод ПолучитьОбъект() для результатов выборки.

Главная ошибка заключается в том, что метод ПолучитьОбъект() предназначен исключительно для считывания и изменения уже существующих в базе данных элементов. Если справочник изначально пустой или запрос возвращает ссылку на ранее записанный объект, вызов ПолучитьОбъект() не создает новую запись, а считывает имеющийся элемент и перезаписывает его реквизиты новыми данными из очередной строки Excel.

Разберем правильный алгоритм создания элементов

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


Для Каждого Стр Из ТЗКонтрагентов Цикл

    // Создаем новый элемент справочника моделей
    НоваяМодель = Справочники.асМодели.СоздатьЭлемент();
    НоваяМодель.Наименование = Стр.Марка + " " + Стр.Модель + " " + Стр.Поколение;
    НоваяМодель.НаименованиеПолное = Стр.Марка + " " + Стр.Модель + " " + Стр.Поколение + " (" + Стр.Годот + "-" + Стр.ГодДо + ")";
    
    Попытка
        НоваяМодель.Записать();
    Исключение
        Сообщить("Не удалось записать модель: " + ОписаниеОшибки());
        Продолжить;
    КонецПопытки;

    // Создаем подчиненный элемент (комплектацию)
    НоваяКомплектация = Справочники.асВариантыКомплектации.СоздатьЭлемент();
    НоваяКомплектация.Наименование = Стр.Модификация + " кузов " + Стр.Серия;
    НоваяКомплектация.НаименованиеПолное = Стр.Модификация + " (" + Стр.Годот + "-" + Стр.ГодДо + ") кузов " + Стр.Серия;
    
    // Владельцем назначаем ссылку только что записанной модели
    НоваяКомплектация.Владелец = НоваяМодель.Ссылка;
    
    Попытка
        НоваяКомплектация.Записать();
    Исключение
        Сообщить("Не удалось записать комплектацию: " + ОписаниеОшибки());
    КонецПопытки;

КонецЦикла;

Важные нюансы работы с подчиненными справочниками и поиске дублей

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

  1. Запись владельца перед установкой связи: Нельзя присвоить подчиненному элементу значение реквизита Владелец, если родительский объект еще не записан в базу данных. Вызов метода Записать() для родительского элемента формирует ссылку НоваяМодель.Ссылка, которая затем успешно передается подчиненному элементу.
  2. Проверка на дубли: Повторный запуск обработки с прямым вызовом СоздатьЭлемент() приведет к дублированию записей. В реальных задачах перед созданием нового элемента рекомендуется проверять его наличие в базе с помощью методов НайтиПоНаименованию(), НайтиПоРеквизиту() или посредством запроса.
  3. Безопасная обработка имен колонок: При считывании заголовков ячеек Excel для генерации колонок таблицы значений важно учитывать, что имя колонки в 1С должно быть валидным идентификатором (без спецсимволов, скобок, знаков препинания и не должно начинаться с цифры).

Альтернативный вариант чтения Excel без COM-соединения

Использование COM-объекта Excel.Application имеет ряд существенных ограничений: требуется наличие установленного MS Excel на рабочем месте, код не работает на серверах под управлением Linux и медленно обрабатывает большие объемы данных. Для более надежной и быстрой загрузки рекомендуется использовать встроенный объект ТабличныйДокумент:


ТабДок = Новый ТабличныйДокумент;
Попытка
    ТабДок.Прочитать(Объект.ВыборФайла);
Исключение
    Сообщить("Ошибка при чтении файла: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

// Проход по строкам табличного документа
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
    ТекстЯчейки = ТабДок.ПолучитьОбласть(НомерСтроки, 1).ТекущаяОбласть.Текст;
    // Логика заполнения и создания элементов
КонецЦикла;

Метод ТабличныйДокумент.Прочитать() работает кроссплатформенно, быстро считывает файлы форматов .xls, .xlsx и .ods, а также не оставляет зависших процессов в оперативной памяти компьютера.

← На главную