Introdução: por que "sem Office" e o que tem dentro?
\n\nSe você já procurou como gerar um arquivo Excel em C#, certamente se deparou com a pergunta icônica no Stack Overflow com dezenas de milhares de visualizações. E a principal dor ali é a frase "without installing Microsoft Office". Por quê? Porque arrastar objetos COM, depender da versão do Excel no servidor e pegar erros como "Retrieving the COM class factory for component... failed" é um caminho infernal para o desenvolvedor.
\n\nMas como então criar arquivos .XLSX e .XLS? A resposta está em como o próprio formato é estruturado. O Excel moderno (a partir de 2007) é simplesmente um arquivo ZIP com arquivos XML dentro. Sim, você não leu errado: pegue qualquer .xlsx, renomeie para .zip, abra — e verá as pastas xl, _rels, docProps e vários documentos XML. Cada planilha, cada célula, cada estilo é um XML cuidadosamente estruturado. Já o formato antigo .XLS é um formato binário (BIFF), mas também existem soluções open-source para ele.
Neste artigo, vamos olhar por baixo dos panos desse processo: analisaremos bibliotecas populares, escreveremos código funcional e entenderemos o que realmente acontece quando chamamos Save(). Vamos nessa!
1. Os três pilares do C# para trabalhar com Excel sem Office
\n\nAtualmente, existem três principais candidatos que resolvem o problema "de fábrica". Cada um deles trabalha diretamente com o formato, sem passar pelo Office instalado.
\n\n1.1. EPPlus (licença LGPL / Proprietária)
\nA biblioteca mais popular para .NET. Inicialmente era gratuita, mas a partir da versão 5.0 passou a ter licença paga para uso comercial. No entanto, para fins educacionais e projetos pequenos, ainda pode ser usada (a versão 4.5.3.3 é a última gratuita). EPPlus funciona apenas com .XLSX.
\n\nComo funciona por baixo dos panos: EPPlus usa System.IO.Packaging (o tal arquivo ZIP) e gera arquivos XML de acordo com a especificação Office Open XML (OOXML). Ela consegue criar estilos, fórmulas, gráficos — tudo o que você vê no Excel.
1.2. ClosedXML
\nGratuita, open-source (licença MIT). Também funciona apenas com .XLSX. Destaca-se por uma API muito amigável, que lembra o trabalho com o próprio Excel: você trabalha com Workbook, Worksheet, Cell. Por baixo dos panos — o mesmo Open XML, mas o ClosedXML assume toda a rotina de criação da estrutura XML.
1.3. NPOI
\nPort da famosa biblioteca Java Apache POI. A principal vantagem é que funciona tanto com .XLSX (através de XSSFWorkbook) quanto com o antigo .XLS (através de HSSFWorkbook). Gratuito, open-source (Apache 2.0). Ideal se você precisa de suporte a formatos legados.
\n\nPor baixo dos panos para .XLS: NPOI escreve diretamente dados binários no formato BIFF8. É mais complexo que XML, mas não requer compressão.
\n\n2. Escrevendo código: criando um arquivo Excel de três maneiras
\n\nVamos criar um relatório simples com cabeçalhos e dados. Abaixo, exemplos para cada biblioteca.
\n\n2.1. Exemplo com ClosedXML (o mais simples)
\n\nusing ClosedXML.Excel;\n\n// Criando a pasta de trabalho\nusing (var workbook = new XLWorkbook())\n{\n // Adicionando uma planilha\n var worksheet = workbook.Worksheets.Add("Relatório");\n\n // Cabeçalhos\n worksheet.Cell(1, 1).Value = "Nome";\n worksheet.Cell(1, 2).Value = "Idade";\n worksheet.Cell(1, 3).Value = "Cidade";\n\n // Dados\n worksheet.Cell(2, 1).Value = "Ana";\n worksheet.Cell(2, 2).Value = 28;\n worksheet.Cell(2, 3).Value = "Moscou";\n\n worksheet.Cell(3, 1).Value = "Ivan";\n worksheet.Cell(3, 2).Value = 35;\n worksheet.Cell(3, 3).Value = "São Petersburgo";\n\n // Estilo para os cabeçalhos\n var headerRange = worksheet.Range("A1:C1");\n headerRange.Style.Font.Bold = true;\n headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;\n\n // Ajuste automático da largura das colunas\n worksheet.Columns().AdjustToC