Загрузка из эксель (распараллеливание записи при работе с большими файлами)

21.04.25

Интеграция - Загрузка и выгрузка в Excel

Загрузка объемных данных из эксель файлов путем распараллеливания записи.

Регулярно возникают задачи по парсингу файлов эксель. Тема хорошо изучена, однако с некоторой периодичностью возникают нюансы и приходится совершенствовать базовый механизм. В моем случае возникла необходимость закачать в регистр сведений много объемных файлов (~ 1 млн. строк). На загрузку одного файла существующим алгоритмом у меня уходило неприлично большое время - несколько часов. Пришла идея распараллелить запись, путем формирования фоновых заданий, каждое из которых сбрасывает свою порцию данных. В итоге, скорость закачки существенно увеличилась - на один файл время загрузки составило 20-30 мин.

(Кстати, в ряде случаев, существенно помогла и программная оптимизация файла - программное удаление пустых столбцов, которые 1С воспринимала как значимые.)

 

1. Был создан регистр сведений, структура измерений которого совпадает со структурой столбцов исходного файла (чтобы не описывать явным образом типизацию столбцов ТЗ):

ДанныеИзФайла = РегистрыСведений.А.СоздатьНаборЗаписей().Выгрузить();

 

2. Собственно открытие, оптимизация и чтение данных файла эксель:

Попытка
        Excel        = Новый COMОбъект("Excel.Application");        
Исключение 
        Excel = Неопределено;
        Возврат;
КонецПопытки; 
    
Excel.FileValidation = 1;
Попытка
        РабочаяКнига = Excel.WorkBooks;    
        РабочаяКнига.Open(СокрЛП(ИмяФайла));
Исключение 
        Excel = Неопределено;        
        Возврат;
КонецПопытки;                                                  
    
КоличествоЛистов             = Excel.WorkSheets.Count();
Лист                         = Excel.WorkSheets(1);
ИспользуемыйЛист             = Лист.UsedRange;        
КоличествоЯчеек              = Excel.Worksheets(1).Cells(1,1).SpecialCells(11).Row;
ВсегоКолонок = Лист.Cells(1,1).SpecialCells(11).Column;
ВсегоСтрок = Лист.Cells(1,1).SpecialCells(11).Row;
Область = Лист.Range(Лист.Cells(1,1), Лист.Cells(ВсегоСтрок,ВсегоКолонок));

  

//удаление заведомо неиспользуемых столбцов (за НомерМаксимальнойКолонки)

Если НомерМаксимальнойКолонки < ВсегоКолонок Тогда
        ОбластьПустых = Лист.Range(Лист.Cells(1,НомерМаксимальнойКолонки+1), Лист.Cells(ВсегоСтрок,ВсегоКолонок));
        ОбластьПустых.Delete(-4159);
КонецЕсли;    
                
Попытка
        Данные = Область.Value.Выгрузить();
        Excel.ActiveWorkbook.Close(Ложь);            
Исключение
        Excel = Неопределено;
        Возврат;
КонецПопытки;        
            
Попытка
        Excel.QUIT();
        Excel        = Неопределено;
Исключение
        Excel = Неопределено;
        Возврат;
КонецПопытки;

3. Цикл обработки считанных данных:

СчетчикСбросаДанныхВКэш = 0;
ДанныеИзФайлаКоличество = 0;

    
ВсегоСтрок = Данные[0].Количество();
                
Для ТекНомерСтрокиФайла = Ексел_НомерСтрокиНачало-1 По ВсегоСтрок-1 Цикл        
        Если СчетчикСбросаДанныхВКэш = ЧислоЗаписейДляСброса Тогда
            ВызватьСопоставитьНаСервере_ДобавитьВРС(ДатаДанных, ДанныеИзФайла, НомерПервойСтрокиПорции,МассивКлючейФоновыхЗаданий);
            ДанныеИзФайлаКоличество = ДанныеИзФайлаКоличество + ДанныеИзФайла.Количество();
            ДанныеИзФайла.Очистить();
            СчетчикСбросаДанныхВКэш = 0;
                
            НомерПервойСтрокиПорции = НомерПервойСтрокиПорции + ЧислоЗаписейДляСброса;

        КонецЕсли;
        СчетчикСбросаДанныхВКэш = СчетчикСбросаДанныхВКэш + 1;    
            
        НовСтр = ДанныеИзФайла.Добавить();         
        Для j = 0 По ВсегоКолонок - 1 Цикл
            Если j = ВсегоКолонок - 1 Тогда  //запись ресурса РС, в моем случае Количество
                НовСтр.Количество = Данные[j][ТекНомерСтрокиФайла];
            Иначе    
                НовСтр[ДанныеИзФайла.Колонки[j+1].Имя] = Данные[j][ТекНомерСтрокиФайла];
            КонецЕсли;    
        КонецЦикла;          
    КонецЦикла;    

4. Финальный сброс данных    

    

ВызватьСопоставитьНаСервере_ДобавитьВРС(ДатаДанных, ДанныеИзФайла, НомерПервойСтрокиПорции,МассивКлючейФоновыхЗаданий);
    ДанныеИзФайлаКоличество = ДанныеИзФайлаКоличество + ДанныеИзФайла.Количество();
            
    //ждем выполнения всех фоновых, с ним связанных
    НеВсеВыполнены = Истина;
    Пока НеВсеВыполнены Цикл 
        _ОбщиеФункции.Задержка(20);
        МассивФоновыхЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания();
        Для Каждого Эл Из МассивФоновыхЗаданий Цикл       
            Индекс_ = МассивКлючейФоновыхЗаданий.Найти(Эл.Ключ);
            Если Индекс_ <> Неопределено И Эл.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
                МассивКлючейФоновыхЗаданий.Удалить(Индекс_);
            КонецЕсли;    
            НеВсеВыполнены = МассивКлючейФоновыхЗаданий.Количество() > 0;
        КонецЦикла;    
    КонецЦикла;


 

Jтдельная процедура по формированию и вызову фонового задания для сброса данных:

&НаСервере
Процедура ВызватьСопоставитьНаСервере_ДобавитьВРС(ДатаОтбора,ТЗ_Загруженная,НачальныйНомерСтроки,МассивКлючейФоновыхЗаданий)    
    
    Структура = Новый Структура;
    Структура.Вставить("ДатаОтбора", ДатаОтбора);
    Структура.Вставить("ТЗ_Загруженная", ТЗ_Загруженная);
    Структура.Вставить("НачальныйНомерСтроки", НачальныйНомерСтроки);
    ПараметрыВыполнения = Новый Массив;
    ПараметрыВыполнения.Добавить(Структура);                               
    КлючФоновогоЗадания = "_"+Формат(ДатаОтбора,"ДФ=dd.MM.yy")+"_"+НачальныйНомерСтроки+"_/"+Формат(ТекущаяДата(),"ДФ=с.мс");
    МассивКлючейФоновыхЗаданий.Добавить(КлючФоновогоЗадания);
    ФоновыеЗадания.Выполнить("_ОбщиеФункции.СопоставитьНаСервере_ДобавитьВРС",ПараметрыВыполнения,КлючФоновогоЗадания,КлючФоновогоЗадания);
        
КонецПроцедуры

 

В моем случае _ОбщиеФункции - это общий модуль со свойствами "Сервер", "Вызов сервера".
 

Процедура СопоставитьНаСервере_ДобавитьВРС(Параметры) Экспорт
    
    ДатаОтбора                 = Параметры.ДатаОтбора;
    ТЗ_Загруженная             = Параметры.ТЗ_Загруженная;    
    НачальныйНомерСтроки     = Параметры.НачальныйНомерСтроки;
    ЗаписыватьИзменения     = Истина;    //ЗначениеЗаполнено(ИмяФайла);
    НомерСтроки             = НачальныйНомерСтроки;
    
    Если ТЗ_Загруженная.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;    
    
    Колонки = ТЗ_Загруженная.Колонки;
    
    Для Каждого Стр Из ТЗ_Загруженная Цикл
        
        НомерСтроки = НомерСтроки + 1;
                                   
        НовЗапись = РегистрыСведений.А.СоздатьМенеджерЗаписи();
        Для Каждого Кол Из Колонки Цикл
            НовЗапись[Кол.Имя] = Стр[Кол.Имя];        
        КонецЦикла;
        

        НовЗапись.Записать(Истина);                  
                    
    КонецЦикла;  
        
КонецПроцедуры

В итоге получается компактное и быстро прикручиваемое решение по считыванию больших файлов. В моменте число фоновых заданий может достигать числа 130-150, каждое из которых работает около 2 минут. Для себя эмпирически установил размер сбрасываемой порции в 3000 строк.

Вступайте в нашу телеграмм-группу Инфостарт

См. также

SALE! 30%

Загрузка и выгрузка в Excel Оптовая торговля Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 2.0 1С:Бухгалтерия 3.0 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:Комплексная автоматизация 1.х 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 10 1С:Управление торговлей 11 1С:Розница 2 1С:Розница 3.0 Бухгалтерский учет Управленческий учет Платные (руб)

Универсальная обработка для загрузки документов из Excel в 1С. Забудьте о ручном вводе: загружайте документы из Excel в 1С за секунды! Не требует указания параметров (номера колонок, номер первой строки таблицы и т.д.) и предварительной настройки. Просто выбираете файл эксель, документ 1С и нажимаете кнопку "Загрузить"

8000 7200 руб.

09.11.2016    272282    1202    957    

1113

Загрузка и выгрузка в Excel Розничная торговля Логистика, склад и ТМЦ Ценообразование, анализ цен Прайсы Системный администратор Программист 1С:Предприятие 8 1С:Комплексная автоматизация 1.х 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Управленческий учет Платные (руб)

Загрузка номенклатуры из файлов Excel (xls, xlsx, ods, csv, mxl) в УТ11, КА 2, ERP 2, Розница 2. Задействованы все возможности конфигурации - заполнение реквизитов номенклатуры, дополнительных реквизитов и сведений, характеристики, доп.реквизиты и сведения характеристик. Дополнительные обработки для расширения возможностей.

12444 руб.

29.10.2014    231150    743    532    

495

Загрузка и выгрузка в Excel Логистика, склад и ТМЦ Ценообразование, анализ цен Файловый обмен (TXT, XML, DBF), FTP Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Эволюция не стоит на месте - новая удобная версия функциональной обработки для Вашего бизнеса! Что же Вы получаете? Удобный и интуитивно понятный интерфейс с 3-мя этапами работы. 2 режима - автоматический и ручной. Чтение XLSX, XLSM, CSV, XML/YML форматов без офиса, на любом сервере! Визуальное связывание колонок файла и реквизитов простым перетаскиванием колонок. Создание или обновление номенклатуры с иерархией, характеристик, доп. реквизитов, упаковок, загрузка практически неограниченного количества картинок на одну номенклатуру (с возможностью загрузки в несколько потоков одновременно), с хранением в томах или в базе. Загрузка номенклатуры поставщиков или поиск по их данным номенклатуры. Загрузка доп. реквизитов в характеристики. Загрузка штрихкодов с генерацией новых. Создание элементов справочников и ПВХ "на лету" для выбранных реквизитов. (Обновление от 27.03.2026, версия 9.3.1 - 10.7.1)

20740 руб.

20.11.2015    173442    426    396    

542

Загрузка и выгрузка в Excel Маркетплейсы Программист Бухгалтер Пользователь 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Бухгалтерский учет Управленческий учет Платные (руб)

Загружает данные из Акта приемки товара от ООО «Вайлдберриз», полученный из личного кабинета в формате *.xlsx или API в документ "Реализация (акты, накладные, УПД)" для конфигурации: Бухгалтерия предприятия, редакция 3.0, в документ "Реализация товаров и услуг" для Управление торговлей, редакция 11; Комплексная автоматизация 2; ERP 2 Управление предприятием и в документ "Расходная накладная" для Управление нашей фирмой 3.0; Розница 3.0

6100 руб.

24.01.2021    24594    120    0    

62

WEB-интеграция Загрузка и выгрузка в Excel Программист Пользователь 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Розничная и сетевая торговля (FMCG) Россия Платные (руб)

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

12200 руб.

29.08.2025    2492    6    6    

8
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. fuser 3 29.04.25 06:10 Сейчас в теме
А не быстрее загружать целиком?
ТабличныйДокумент.Прочитать(ФайлEXCEL, СпособЧтенияЗначенийТабличногоДокумента.Значение);
2. ko-@ 2 05.05.25 11:00 Сейчас в теме
(1) У меня стояла задача перенести из прочитанного файла (уже из таблицы значений) данные в регистр сведений. Без распараллеливания этот процесс занимает крайне много времени. Собственно, использование фоновых заданий, каждое из которых пишет в регистр свою порцию в десятки раз сокращает время обработки.

Сам контекст задачи был таков, что исходный файл эксель мог содержать как избыточные данные, так и требующие предварительной обработки (преобразование значений). Поэтому требуется как предварительная обработка файла эксель средствами VBA, так и построчная проверка значений. Я использовал метод

Данные = Область.Value.Выгрузить();

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