Как ускорить выгрузку табеля учета рабочего времени из 1С в Excel

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

При формировании и выгрузке табелей учета рабочего времени из 1С в Microsoft Excel разработчики часто сталкиваются с существенным замедлением работы: выгрузка одного документа может занимать от 60 до 90 секунд. Проанализируем, почему возникает эта проблема, и разберем практические способы ускорения процесса в десятки раз.

Выясним причины низкой скорости выгрузки

Основная причина медленной работы кроется в архитектуре взаимодействия 1С с Microsoft Excel через COM-соединение:

  1. Межпроцессные вызовы (IPC/OLE overhead): При классическом поячеечном заполнении таблицы через конструкции вида Cells(i, j).Value = ... каждый вызов из среды 1С в отдельный процесс EXCEL.EXE создает накладные расходы. В табеле за месяц на десятки сотрудников с учетом всех дней, видов времени и форматирования количество таких обращений достигает десятков тысяч.
  2. Автоматические пересчеты и перерисовка: По умолчанию Excel при записи данных в каждую ячейку пытается обновить экран, пересчитать формулы книги и отработать внутренние события.
  3. Поячеечное форматирование: Установка границ, шрифтов, выравнивания и заливки для каждой ячейки по отдельности генерирует еще больше COM-вызовов.

Способ 1. Оптимизация прямого взаимодействия через COM-объект

Если логика выгрузки жестко завязана на COM-объект Excel, оптимизируем код без изменения общей архитектуры. Разберем необходимые шаги:

  1. Отключение визуальных и расчетных механизмов Excel: Перед началом записи данных необходимо временно отключить перерисовку экрана, автоматический расчет формул и обработку событий.
  2. Пакетная передача данных через массив: Вместо заполнения ячеек по одной сформируем двумерный массив в памяти 1С и передадим его в диапазон Excel за один COM-вызов.
  3. Групповое форматирование: Оформление (границы, шрифты, выравнивание) следует применять не к отдельным ячейкам, а сразу ко всему диапазону Range.

Посмотрим на пример правильной организации пакетной выгрузки:


Попытка
    Эксель = Новый COMОбъект("Excel.Application");
    Книга = Эксель.Workbooks.Add();
    Лист = Книга.Worksheets(1);
    
    // Отключаем лишние обработчики для ускорения работы
    Эксель.ScreenUpdating = Ложь;
    Эксель.Calculation = -4135; // xlCalculationManual
    Эксель.EnableEvents = Ложь;
    Эксель.DisplayAlerts = Ложь;
    
    // Формируем двумерный массив данных в памяти 1С
    // КоличествоСтрок и КоличествоКолонок определяются по данным табеля
    МассивДанных = Новый COMSafeArray("VT_VARIANT", КоличествоСтрок, КоличествоКолонок);
    
    Для НомерСтроки = 0 По КоличествоСтрок - 1 Цикл
        Для НомерКолонки = 0 По КоличествоКолонок - 1 Цикл
            МассивДанных.SetValue(НомерСтроки, НомерКолонки, ПолучитьЗначениеТабеля(НомерСтроки, НомерКолонки));
        КонецЦикла;
    КонецЦикла;
    
    // Записываем весь массив данных одним вызовом
    Диапазон = Лист.Range(Лист.Cells(1, 1), Лист.Cells(КоличествоСтрок, КоличествоКолонок));
    Диапазон.Value = МассивДанных;
    
    // Применяем групповое форматирование к диапазону
    Диапазон.Borders.LineStyle = 1; // xlContinuous
    
    // Устанавливаем защиту на лист
    Лист.Protect("ПарольЗащиты");
    
    // Включаем параметры обратно перед сохранением
    Эксель.ScreenUpdating = Истина;
    Эксель.Calculation = -4105; // xlCalculationAutomatic
    Эксель.EnableEvents = Истина;
    Эксель.DisplayAlerts = Истина;
    
    Книга.SaveAs(ПутьКФайлу);
    Книга.Close(Ложь);
    Эксель.Quit();
Исключение
    Если Эксель <> Неопределено Тогда
        Эксель.Quit();
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;

// Очищаем COM-переменные для освобождения процесса в памяти
Лист = Неопределено;
Книга = Неопределено;
Эксель = Неопределено;

Способ 2. Комбинированный метод: Табличный документ + COM

Рассмотрим наиболее производительный и простой в поддержке вариант. Платформа 1С умеет формировать сложные печатные формы с любым оформлением за доли секунды. Если требуется сохранить форматирование и запаролить лист, разделим задачу на два этапа:

  1. Формируем табель штатными средствами в объект ТабличныйДокумент с макетом, объединением ячеек, шрифтами и цветами, после чего сохраняем его в файл XLSX.
  2. Открываем готовый файл через COM-объект Excel, накладываем пароль на лист методом Protect, сохраняем и закрываем книгу.

Разберем по шагам реализацию данного подхода:


// Этап 1: Формирование и сохранение табличного документа средствами 1С
ТабДокумент = Новый ТабличныйДокумент;
// ... Заполнение табеля данными и оформлением через макет ...

ИмяФайла = "C:\Temp\Табель.xlsx";
ТабДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);

// Этап 2: Наложение пароля на готовый файл через COM
Попытка
    Эксель = Новый COMОбъект("Excel.Application");
    Эксель.DisplayAlerts = Ложь;
    Эксель.ScreenUpdating = Ложь;
    
    Книга = Эксель.Workbooks.Open(ИмяФайла);
    Лист = Книга.Worksheets(1);
    
    // Установка защиты листа
    Лист.Protect("СекретныйПароль");
    
    Книга.Save();
    Книга.Close(Ложь);
    Эксель.Quit();
Исключение
    Если Эксель <> Неопределено Тогда
        Эксель.Quit();
    КонецЕсли;
    ВызватьИсключение;
КонецПопытки;

Лист = Неопределено;
Книга = Неопределено;
Эксель = Неопределено;

Данный подход сокращает общее время выгрузки с 75 секунд до 1–2 секунд, так как отрисовка документа полностью выполняется внутри платформы 1С без накладных расходов на COM-вызовы.

Способ 3. Выгрузка в формат SpreadsheetML (XML Spreadsheet 2003)

Проанализируем альтернативный вариант, который позволяет полностью отказаться от наличия Microsoft Excel на компьютере пользователя или сервере. Формат XML Spreadsheet представляет собой файл с разметкой XML, который открывается в Excel как полноценная таблица.

  1. Формируем файл через ЗаписьXML или ЗаписьТекста с расширением .xml (или .xls).
  2. Задаем стили ячеек, ширину колонок и объединения прямо в структуре XML.
  3. Защита листа устанавливается встроенным тегом разметки <WorksheetOptions><ProtectObjects>True</ProtectObjects></WorksheetOptions>.

Такой способ формируется мгновенно в оперативной памяти и не создает фоновых процессов в операционной системе.

Рекомендации по корректному завершению процессов Excel

При работе с COM-объектами важно предотвращать зависание процессов EXCEL.EXE в диспетчере задач. Обратим внимание на обязательные правила:

  1. Всегда оборачивайте работу с внешними приложениями в блок Попытка ... Исключение.
  2. В блоке завершения и обработки ошибок обязательно вызывайте Эксель.Quit().
  3. После закрытия приложения явно очищайте ссылки на объекты (Эксель = Неопределено), чтобы сборщик мусора платформы 1С освободил COM-дескриптор.
← На главную