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

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 строк.

См. также

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

Реальный помощник, с помощью которого Вы преобразуете необходимые документы для Wildberries, OZON, ЯндексМаркет, Мегамаркет, Aliexpress, Детский мир, МагнитЭкспресс (быв.Казань-Экспресс), Леруа Мерлен, ЭНФАНТА (Акушерство), ЛаМода, Летуаль, Твой дом, Золотое Яблоко в документы "Отчет комиссионера (агента) о продажах" и другие. Работает в 1С:БП 3.0, 1С:БП 3.0 КОРП, 1С:УТ 11, 1С:УНФ, 1С:КА 2, 1С:ERP Управление предприятием.

5400 руб.

12.08.2021    39153    444    69    

180

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

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

8000 руб.

09.11.2016    247452    1137    915    

1058

Загрузка и выгрузка в Excel Логистика, склад и ТМЦ Ценообразование, анализ цен Файловый обмен (TXT, XML, DBF), FTP Бухгалтер Пользователь Платформа 1С v8.3 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 форматов без офиса, на любом сервере! Визуальное связывание колонок файла и реквизитов простым перетаскиванием колонок. Создание или обновление номенклатуры с иерархией, характеристик, доп. реквизитов, упаковок, загрузка практически неограниченного количества картинок на одну номенклатуру (с возможностью загрузки в несколько потоков одновременно), с хранением в томах или в базе. Загрузка номенклатуры поставщиков или поиск по их данным номенклатуры. Загрузка доп. реквизитов в характеристики. Загрузка штрихкодов с генерацией новых. Создание элементов справочников и ПВХ "на лету" для выбранных реквизитов. (Обновление от 13.05.2025, версия 9.11 - 1010)

18000 руб.

20.11.2015    161376    400    386    

527

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

Загрузка данных отчета о реализации и продаже товаров из сервиса Яндекс.Маркета «Беру» из отчетов Excel для конфигурации: Бухгалтерия предприятия, редакция 3.0; Управление торговлей, редакция 11; Управление торговлей, редакция 10.3; Управление нашей фирмой, редакция 3.0 и Розница, редакция 3.0 в документ «Отчет комиссионера о продажах».

6000 руб.

09.12.2020    27390    282    1    

136

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

Обработки загрузки данных о продажах WildBerries предназначены для следующих конфигураций: Бухгалтерия предприятия, редакция 3.0; Управление нашей фирмой, редакция 3.0; Розница, редакция 3.0; Управление торговлей, редакция 11; Управление торговлей, редакция 10.3

6000 руб.

11.12.2019    60166    1030    3    

265

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

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

11100 руб.

29.10.2014    219723    674    528    

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

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

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

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