Как загрузить данные из Excel в регистр сведений 1С без потери порядка строк?

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

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

Причина проблемы: особенности архитектуры регистров сведений

Для начала проанализируем ситуацию с точки зрения теории платформы. Регистр сведений — это прикладной объект, предназначенный для хранения многомерных данных. В отличие от справочников, у него нет стандартных полей Код или Наименование, а его уникальность определяется набором измерений.

Выясним причину, почему типовая обработка ведет себя именно так:

  1. Уникальность записей: Если у непериодического регистра нет измерений, система сможет хранить в нем только одну-единственную запись. Любая попытка записать новую строку приведет к перезаписи существующей. Поэтому типовая обработка требует указать хотя бы одно поле в качестве измерения.
  2. Отсутствие физического порядка: В реляционных базах данных (SQL), на которых базируется 1С, записи не имеют гарантированного «естественного» порядка. Порядок строк в Excel — это просто их индекс в файле. Чтобы сохранить этот порядок в 1С, его нужно зафиксировать в данных.

Решение 1: Использование «искусственного измерения» (самый быстрый способ)

Если перед нами стоит задача разовой загрузки в рамках проекта со строгими сроками, и мы не хотим тратить время на написание собственного кода, можно воспользоваться методом, предложенным в ходе обсуждения. Для регистров же суть заключается в том, чтобы привести структуру Excel-файла в соответствие с требованиями объектной модели 1С.

Разберем этот метод по шагам:

  1. Откроем исходный файл Excel.
  2. Добавим в таблицу новую колонку (например, в самом начале), назовем ее НомерСтроки.
  3. Заполним эту колонку порядковыми номерами. Проще всего это сделать с помощью автозаполнения или формулы =СТРОКА(). Это позволит нам пронумеровать все позиции «как есть».
  4. В конфигураторе 1С в целевом регистре сведений создадим новое измерение с именем НомерСтроки и типом Число.
  5. Запустим типовую обработку ЗагрузкаДанныхИзТабличногоДокумента.epf.
  6. При настройке полей сопоставим нашу колонку НомерСтроки с соответствующим измерением регистра.

Таким образом, мы решаем сразу две задачи: удовлетворяем требование обработки о наличии измерения и фиксируем порядок строк. При извлечении данных из регистра нам достаточно будет просто установить сортировку по полю НомерСтроки.

Решение 2: Программная загрузка данных (гибкий подход)

Если типовая обработка не подходит по функционалу или требуется автоматизировать процесс для регулярного использования, наиболее эффективным решением будет написание собственной небольшой процедуры. В качестве отправной точки можно использовать шаблон простой обработки загрузки из excel, который легко адаптировать под свои нужды.

Проанализируем ситуацию: для экономии времени можно скопировать содержимое Excel прямо в макет обработки или прочитать файл в объект ТабличныйДокумент. Посмотрим на пример реализации:


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

    ВысотаТаблицы = ТабДок.ВысотаТаблицы;
    
    // Начинаем со второй строки, предполагая, что первая - заголовок
    Для Инд = 2 По ВысотаТаблицы Цикл
        
        // Создаем менеджер записи для каждой строки
        МенеджерЗаписи = РегистрыСведений.ИмяВашегоРегистра.СоздатьМенеджерЗаписи();
        
        // Читаем данные из колонок ТабДока
        МенеджерЗаписи.Измерение1 = СокрЛП(ТабДок.Область(Инд, 1).Текст);
        МенеджерЗаписи.Ресурс1    = ТабДок.Область(Инд, 2).Текст;
        
        // Если мы добавили искусственное измерение НомерСтроки:
        МенеджерЗаписи.НомерСтроки = Инд; 
        
        Попытка
            МенеджерЗаписи.Записать(Истина); // Истина - замещать существующую запись
        Исключение
            Сообщить("Ошибка в строке " + Инд + ": " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;
    
    Сообщить("Загрузка завершена!");
КонецПроцедуры

Использование метода СоздатьМенеджерЗаписи() удобно для простых случаев, когда объем данных невелик. Если же строк десятки тысяч, использование менеджера записи в цикле будет работать медленно.

Оптимизация: Использование набора записей

Для ускорения процесса загрузки в проектах, где важна производительность, рекомендуется использовать РегистрСведенийНаборЗаписей. Это позволит записать данные «порциями» или одним махом. Для предварительного анализа данных перед записью может пригодиться портативная обработка чтения файла в таблицу, позволяющая манипулировать данными прямо в консоли кода.

Рассмотрим подробнее, как применить этот механизм. В режиме загрузки данных из внешнего источника крайне важно использовать свойство ОбменДанными.Загрузка = Истина. Это отключает проверки в модуле набора записей, ускоряя процесс и помогая избежать блокировок.


Набор = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
// Если нужно полностью заменить данные, фильтр не ставим, 
// но вызываем Набор.Записать() в конце.

Для Инд = 2 По ВысотаТаблицы Цикл
    НоваяЗапись = Набор.Добавить();
    НоваяЗапись.Измерение1 = ТабДок.Область(Инд, 1).Текст;
    НоваяЗапись.Ресурс1    = ТабДок.Область(Инд, 2).Текст;
    НоваяЗапись.НомерСтроки = Инд;
КонецЦикла;

Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();

Альтернативные методы чтения Excel в современных версиях 1С

Начиная с версии платформы 8.3.6, у разработчиков появились мощные встроенные инструменты для работы с файлами .xlsx. Если вам требуется поддержка нескольких листов или работа с CSV, рекомендуем обратить внимание на универсальную загрузку файлов Excel и CSV, которая возвращает коллекцию листов в виде таблиц значений — для этого подойдёт универсальная загрузка данных из Excel и CSV.

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

Подведем итоги

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

  1. Использовать «костыль» с нумерацией строк в Excel, если нужно решить задачу «здесь и сейчас» типовыми средствами.
  2. Создать собственную обработку на 10-15 строк кода, если требуется гибкость.
  3. Обязательно добавлять искусственное измерение (ID или НомерСтроки), если порядок данных в плоской таблице Excel имеет значение для последующей обработки в 1С.
  4. Для частных случаев, таких как загрузка списка значений доп. реквизитов, использовать специализированные внешние обработки.

Помните, что регистр сведений — это не просто таблица, а ключ-значение, где ключом является совокупность измерений. Грамотное проектирование структуры регистра на этапе разработки избавит вас от проблем с загрузкой в будущем.

← На главную