Otimização da Exportação de Dados para Excel em C# para Resolver Problemas de Performance

Introdução: Ao exportar dados para Excel, o processo estava apresentando lentidão significativa.

Código original:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IPC.Helper
{
    class ExcelExportUtil
    {
        public static string expotExcel(List<DataTable> tabelasHistorico, string[] nomesTipos, string nomeArquivoSalvo)
        {
            try
            {
                Microsoft.Office.Interop.Excel.Application aplicacaoExcel = new Microsoft.Office.Interop.Excel.Application();
                if (aplicacaoExcel == null)
                {
                    return "Não foi possível criar objeto Excel. O Excel pode não estar instalado neste computador";
                }

                Microsoft.Office.Interop.Excel.Workbooks workbooks = aplicacaoExcel.Workbooks;
                Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
                Microsoft.Office.Interop.Excel.Worksheet worksheet3 = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];
                Microsoft.Office.Interop.Excel.Worksheet worksheet2 = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets.Add(Type.Missing,Type.Missing,Type.Missing,Type.Missing);
                worksheet2.Name = nomesTipos[0];

                // Escrevendo cabeçalho
                int contadorTitulos = 1;
                worksheet2.Cells[1, contadorTitulos++] = "Tempo 1";
                worksheet2.Cells[1, contadorTitulos++] = "Valor Parâmetro";
                worksheet2.Cells[1, contadorTitulos++] = "Valor Máximo";
                worksheet2.Cells[1, contadorTitulos++] = "Valor Mínimo";

                // Obtendo hora atual
                DateTime agora = DateTime.Now;
                string horaFormatada = agora.ToString("yyyy-MM-dd HH:mm:ss");
                Console.WriteLine(horaFormatada);
				
                // Escrevendo valores
                for (int r = 0; r < tabelasHistorico[0].Rows.Count; r++)
                {
                    int contadorLinhas = 1;
                    worksheet2.Cells[r + 2, contadorLinhas++] = " " + tabelasHistorico[0].Rows[r]["data_time"].ToString() + "\t";
                    worksheet2.Cells[r + 2, contadorLinhas++] = tabelasHistorico[0].Rows[r]["conc"].ToString();
                    worksheet2.Cells[r + 2, contadorLinhas++] = tabelasHistorico[0].Rows[r]["max"].ToString();
                    worksheet2.Cells[r + 2, contadorLinhas++] = tabelasHistorico[0].Rows[r]["min"].ToString();
                    System.Windows.Forms.Application.DoEvents();
                }
				
                // Obtendo hora atual novamente
                DateTime agora1 = DateTime.Now;
                string horaFormatada1 = agora1.ToString("yyyy-MM-dd HH:mm:ss");
                Console.WriteLine(horaFormatada1);
				
                worksheet2.Columns.EntireColumn.AutoFit(); // Ajuste automático de largura de colunas

                workbook.Saved = true;
                workbook.SaveCopyAs(nomeArquivoSalvo);

                aplicacaoExcel.Quit();
                GC.Collect(); // Forçando coleta de lixo

                return "Exportação concluída com sucesso";
            }
            catch(Exception e)
            {
                return e.Message;
            }
        }
    }
}

Ao adicionar registros de tempo ao código, descobriu-se que o loop de escrita estava levando cerca de 35 segundos para quase 3000 registros. Após otimização, o tempo foi reduzido para apenas 1 segundo.

Estratégias de otimização: 1. No loop for, mover o contador de tamanho para fora do loop, pois chamadas repetidas a .size() causam lentidão;

  1. Ao escrever no Excel, evitar a escrita célula por célula e usar escrita em renge (entervalo) em vez disso;

Parte de escrita de dados, código modificado:

                object[,] cabecalho = worksheet2.Range["A1", "D1"].Value2;
                cabecalho[1, 1] = "Tempo";
                cabecalho[1, 2] = "Valor Parâmetro";
                cabecalho[1, 3] = "Valor Máximo";
                cabecalho[1, 4] = "Valor Mínimo";
                worksheet2.Range["A1", "D1"].Value2 = cabecalho;

                // Escrevendo valores
                int totalLinhas = tabelasHistorico[0].Rows.Count;
                string ultimoIntervalo = "D" + totalLinhas + 1;
                object[,] dados = worksheet2.Range["A2", ultimoIntervalo].Value2;      
                
                for (int r = 0; r < totalLinhas; r++)
                {
                    dados[r+1, 1] = " " + tabelasHistorico[0].Rows[r]["data_time"].ToString() + "\t";
                    dados[r+1, 2] = tabelasHistorico[0].Rows[r]["conc"].ToString();
                    dados[r + 1, 3] = tabelasHistorico[0].Rows[r]["max"].ToString();
                    dados[r + 1, 4] = tabelasHistorico[0].Rows[r]["min"].ToString();

                    System.Windows.Forms.Application.DoEvents();
                }
                worksheet2.Range["A2", ultimoIntervalo].Value2 = dados;

Tags: C# Excel Otimização de Performance Interoperabilidade Exportação de Dados

Publicado em 7-2 23:15