Lendo arquivos do Excel em C #


233

Existe uma biblioteca gratuita ou de código aberto para ler arquivos do Excel (.xls) diretamente de um programa em C #?

Não precisa ser muito sofisticado, apenas para selecionar uma planilha e ler os dados como strings. Até agora, tenho usado a função de texto Exportar para Unicode do Excel e analisando o arquivo resultante (delimitado por tabulações), mas gostaria de eliminar a etapa manual.

Respostas:


153
var fileName = string.Format("{0}\\fileNameHere", Directory.GetCurrentDirectory());
var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", fileName);

var adapter = new OleDbDataAdapter("SELECT * FROM [workSheetNameHere$]", connectionString);
var ds = new DataSet();

adapter.Fill(ds, "anyNameHere");

DataTable data = ds.Tables["anyNameHere"];

Isto é o que eu costumo usar. É um pouco diferente, porque normalmente colo um AsEnumerable () na edição das tabelas:

var data = ds.Tables["anyNameHere"].AsEnumerable();

pois isso permite que eu use o LINQ para pesquisar e criar estruturas a partir dos campos.

var query = data.Where(x => x.Field<string>("phoneNumber") != string.Empty).Select(x =>
                new MyContact
                    {
                        firstName= x.Field<string>("First Name"),
                        lastName = x.Field<string>("Last Name"),
                        phoneNumber =x.Field<string>("Phone Number"),
                    });

Se parece que o Selecionar nesta abordagem tenta adivinhar o tipo de dados da coluna e forçar esse tipo de dados adivinhado. Por exemplo, se você tiver uma coluna com valores duplos, não gostará de passar x.Field <string>, mas espera x.Field <double>. Isso é verdade?
— Kevin Le - Khnle

1
Apenas procurei no MSDN. Parece que o <T> é usado apenas para tentar converter o conteúdo da coluna em um tipo. Neste exemplo e apenas convertendo os dados nas colunas para strings. Se você quisesse um double, seria necessário chamar double.Parse (x.Field <string> ("Cost") ou algo assim. Field é um método de extensão para o DataRow e parece que não há versões não genéricas.
— Robin Robinson

Adicionar um double.Parse à consulta Linq diminui muito a velocidade?
— Tipo anônimo

23
Observe que, se você estiver lendo xlsx, precisará usar esta cadeia de conexão:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
— Andreas Grech

7
Infelizmente, o driver Jet.OLEDB não é compatível com 64 bits; você precisará mudar para o destino x86 em vez de Qualquer CPU (se você ainda quiser continuar com esse método). Alternativamente instalar o controlador de ACE de 64 bits e alterar a cadeia conn para usar este condutor (tal como indicado por Andreas) - microsoft.com/en-us/download/...
— Duncan

83

Se forem apenas dados simples contidos no arquivo do Excel, você poderá ler os dados via ADO.NET. Veja as cadeias de conexão listadas aqui:

http://www.connectionstrings.com/?carrier=excel2007 ou http://www.connectionstrings.com/?carrier=excel

-Ryan

Atualização: você pode ler a planilha através de algo como select * from [Sheet1$]


1
Desta forma, é de longe o mais rápido.
— StingyJack

17
Claro que isso não é verdade, mesquinho. Você precisa filtrar todos os dados e escrever códigos de banco de dados ruins (criar manualmente seus modelos, mapear colunas para propriedades, yadda yadda). A maneira mais rápida é deixar que outros SOB pobres façam isso por você . É por isso que as pessoas usam estruturas em vez de escrever tudo de baixo para cima.

12
Método inútil! Trunca colunas de texto para 255 caracteres quando lidas. Cuidado! Veja: stackoverflow.com/questions/1519288/… O mecanismo ACE faz a mesma coisa!
— Triynko

5
Esteja ciente de que o uso do ADO.NET para ler dados do exel requer o Microsoft Access ou o Microsoft Access Database Engine Redistributable instalado.
— zihotki

3
O driver também adivinhará os tipos de colunas com base nas primeiras linhas. Se você tiver uma coluna com o que parece ser inteiros nas primeiras fileiras que você vai encontrar um erro quando você bate um não inteiro (por exemplo, uma bóia, uma string)
— Brian Low

27

A abordagem do ADO.NET é rápida e fácil, mas há algumas peculiaridades que você deve conhecer, especialmente em relação à forma como os DataTypes são tratados.

Este excelente artigo o ajudará a evitar algumas armadilhas comuns: http://blog.lab49.com/archives/196


Você respondeu à minha pergunta (na forma de um comentário acima).
— Kevin Le - Khnle

22

Isto é o que eu usei para o Excel 2003:

Dictionary<string, string> props = new Dictionary<string, string>();
props["Provider"] = "Microsoft.Jet.OLEDB.4.0";
props["Data Source"] = repFile;
props["Extended Properties"] = "Excel 8.0";

StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> prop in props)
{
    sb.Append(prop.Key);
    sb.Append('=');
    sb.Append(prop.Value);
    sb.Append(';');
}
string properties = sb.ToString();

using (OleDbConnection conn = new OleDbConnection(properties))
{
    conn.Open();
    DataSet ds = new DataSet();
    string columns = String.Join(",", columnNames.ToArray());
    using (OleDbDataAdapter da = new OleDbDataAdapter(
        "SELECT " + columns + " FROM [" + worksheet + "$]", conn))
    {
        DataTable dt = new DataTable(tableName);
        da.Fill(dt);
        ds.Tables.Add(dt);
    }
}

2
planilha não está definida ... parece um pouco estranho para mim depois de definir claramente tudo o resto.
— Jeremy Holovacs

21

E o Excel Data Reader?

http://exceldatareader.codeplex.com/

Eu usei essa raiva, em um ambiente de produção, para extrair grandes quantidades de dados de uma variedade de arquivos do Excel para o SQL Server Compact. Funciona muito bem e é bastante robusto.


2
Vou testar o Excel Data Reader; também levou à incrivelmente útil biblioteca Excel Data Driven Tests, que usa o atributo TestCaseSource do NUnit 2.5 para fazer testes controlados por dados usando planilhas do Excel ridiculamente fáceis. Lembre-se de que o Resharper ainda não suporta o TestCaseSource, portanto, você deve usar o corredor NUnit.
— David Keaveny 20/10/10

Infelizmente, há alguns problemas nesta biblioteca que acabamos de encontrar. Em primeiro lugar, tivemos alguns campos de moeda saindo como datas. Em segundo lugar, está falhando se a pasta de trabalho contiver folhas vazias. Portanto, embora tenha sido muito fácil integrar, agora estamos reavaliando se continuaremos usando esta biblioteca. Não parece estar sendo desenvolvido ativamente.
— Ian1971

Ele também pressupõe a presença de alguns elementos opcionais no arquivo xlsx que causam falha na leitura dos dados, caso estejam ausentes.
— RichieHindle

Estamos tendo problemas com arquivos do Excel provenientes do SQL Server Reporting Services. Eles simplesmente não funcionam, a menos que você os abra e os salve (até mesmo sem edição). @ RichieHindle: de quais elementos opcionais você está falando (esperando que isso possa me ajudar com meus arquivos Excel do SSRS)?
— Peter

@ Peter: Eu acho que era um <dimension>elemento ausente no <worksheet>que estava causando problemas para mim.
— precisa saber é o seguinte

16

Aqui está um código que eu escrevi em C # usando o .NET 1.1 há alguns anos atrás. Não tenho certeza se isso seria exatamente o que você precisa (e pode não ser o meu melhor código :)).

using System;
using System.Data;
using System.Data.OleDb;

namespace ExportExcelToAccess
{
    /// <summary>
    /// Summary description for ExcelHelper.
    /// </summary>
    public sealed class ExcelHelper
    {
        private const string CONNECTION_STRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=<FILENAME>;Extended Properties=\"Excel 8.0;HDR=Yes;\";";

        public static DataTable GetDataTableFromExcelFile(string fullFileName, ref string sheetName)
        {
            OleDbConnection objConnection = new OleDbConnection();
            objConnection = new OleDbConnection(CONNECTION_STRING.Replace("<FILENAME>", fullFileName));
            DataSet dsImport = new DataSet();

            try
            {
                objConnection.Open();

                DataTable dtSchema = objConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

                if( (null == dtSchema) || ( dtSchema.Rows.Count <= 0 ) )
                {
                    //raise exception if needed
                }

                if( (null != sheetName) && (0 != sheetName.Length))
                {
                    if( !CheckIfSheetNameExists(sheetName, dtSchema) )
                    {
                        //raise exception if needed
                    }
                }
                else
                {
                    //Reading the first sheet name from the Excel file.
                    sheetName = dtSchema.Rows[0]["TABLE_NAME"].ToString();
                }

                new OleDbDataAdapter("SELECT * FROM [" + sheetName + "]", objConnection ).Fill(dsImport);
            }
            catch (Exception)
            {
                //raise exception if needed
            }
            finally
            {
                // Clean up.
                if(objConnection != null)
                {
                    objConnection.Close();
                    objConnection.Dispose();
                }
            }


            return dsImport.Tables[0];
            #region Commented code for importing data from CSV file.
            //              string strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source=" + System.IO.Path.GetDirectoryName(fullFileName) +";" +"Extended Properties=\"Text;HDR=YES;FMT=Delimited\"";
            //
            //              System.Data.OleDb.OleDbConnection conText = new System.Data.OleDb.OleDbConnection(strConnectionString);
            //              new System.Data.OleDb.OleDbDataAdapter("SELECT * FROM " + System.IO.Path.GetFileName(fullFileName).Replace(".", "#"), conText).Fill(dsImport);
            //              return dsImport.Tables[0];

            #endregion
        }

        /// <summary>
        /// This method checks if the user entered sheetName exists in the Schema Table
        /// </summary>
        /// <param name="sheetName">Sheet name to be verified</param>
        /// <param name="dtSchema">schema table </param>
        private static bool CheckIfSheetNameExists(string sheetName, DataTable dtSchema)
        {
            foreach(DataRow dataRow in dtSchema.Rows)
            {
                if( sheetName == dataRow["TABLE_NAME"].ToString() )
                {
                    return true;
                }   
            }
            return false;
        }
    }
}

Não poderia concordar mais Cherian. Este código é muitos anos ... antes mesmo de eu era acostumado com ReSharper :)
— hitec

2
O código é feio, mas mostra como obter os nomes das planilhas, ótimo!
— Sam

15

Koogra é um componente de código aberto escrito em C # que lê e grava arquivos do Excel.


Não parece particularmente activa mais, em comparação com, digamos, NPOI
— David Burton


8

Eu li muito os arquivos do Excel em C # há um tempo atrás e usamos duas abordagens:

  • A API COM, onde você acessa os objetos do Excel diretamente e os manipula através de métodos e propriedades
  • O driver ODBC que permite usar o Excel como um banco de dados.

A última abordagem foi muito mais rápida: ler uma grande tabela com 20 colunas e 200 linhas levaria 30 segundos via COM e meio segundo via ODBC. Então, eu recomendaria a abordagem de banco de dados se tudo que você precisa são os dados.

Felicidades,

Carl



6

Quero mostrar um método simples para ler o arquivo xls / xlsx com o .NET. Espero que o seguinte seja útil para você.

 DataTable privado ReadExcelToTable (caminho da string)    
 {

     // String de conexão

     string connstring = "Provedor = Microsoft.ACE.OLEDB.12.0; Fonte de dados =" + caminho + "; Propriedades estendidas = 'Excel 8.0; HDR = NÃO; IMEX = 1';";  
     //o mesmo nome 
     // string connstring = Provider = Microsoft.JET.OLEDB.4.0; Fonte de dados = "+ caminho + //"; Propriedades estendidas = 'Excel 8.0; HDR = NO; IMEX = 1'; "; 

     using (OleDbConnection conn = new OleDbConnection (connstring))
     {
        conn.Open ();
        // Obter nome de todas as folhas
        DataTable sheetsName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, novo objeto [] {nulo, nulo, nulo, "Tabela"});  

        // Obter o nome da primeira planilha
        string firstSheetName = sheetsName.Rows [0] [2] .ToString (); 

        // String de consulta 
        string sql = string.Format ("SELECT * FROM [{0}]", firstSheetName); 
        OleDbDataAdapter ada = novo OleDbDataAdapter (sql, connstring);
        Conjunto de dados = novo DataSet ();
        preenchimento (conjunto);
        retornar set.Tables [0];   
   }
 }

O código é do artigo: http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/ . Você pode obter mais detalhes com isso.


2
Ele foi útil, especialmente a parte sobre a leitura de sheetnames.
— 27512 martinstoeckli

4

Não é gratuito, mas com o Office mais recente, existe uma API .Net de automação muito boa. (há uma API há muito tempo, mas a COM é desagradável) Você pode fazer tudo o que deseja / precisa no código enquanto o aplicativo do Office permanece um processo oculto em segundo plano.


3
@ Tipo anônimo Eu li a pergunta e estava oferecendo uma alternativa útil para a implementação OSS desejada ... porque, bem, eu tinha certeza que não havia nada disponível. E, a julgar pela resposta aceita, um requisito de instalação do Office não é um problema.
— Xanadont

3

Perdoe-me se eu estiver fora da base aqui, mas não é para isso que servem os PIA do Office ?


5
Sim, mas isso envolveria a criação de uma instância do Excel.Application, o carregamento do arquivo xls etc. Se o requisito for apenas ler alguns dados do arquivo, será muito mais fácil e muito mais leve usar um dos métodos do ADO.NET descritos nas outras respostas.
— Adam Ralph

Muito devagar, usando o Office PIA como linha de base, todo o resto é mais rápido - mesmo usando apenas uma matriz de objetos passada da propriedade .Value2. Que ainda está usando o PIA.
— Tipo anônimo

3

Ultimamente, em parte para melhorar o LINQ ... Eu tenho usado a API de automação do Excel para salvar o arquivo como planilha XML e, em seguida, obter esse processo usando o LINQ to XML.


Eu suspeitaria que você pode protegê-lo do Excel, mas não do homem com compilador ... como qualquer coisa ... são apenas bytes.
— Kenny 26/05

@gsvirdi, poste uma pergunta separada sobre segurança de arquivos do Excel, esta questão é sobre desempenho.
— Tipo anônimo


3

O SmartXLS é outro componente da planilha do Excel que suporta a maioria dos recursos de gráficos do Excel, mecanismos de fórmulas e pode ler / gravar o formato open200ml do excel2007.



2

Eu recomendo a Biblioteca FileHelpers, que é uma biblioteca .NET gratuita e fácil de usar para importar / exportar dados do EXCEL, comprimento fixo ou registros delimitados em arquivos, strings ou fluxos + Mais.

A seção de documentação do Excel Data Link http://filehelpers.sourceforge.net/example_exceldatalink.html


1
Não vou decepcioná-lo, mas recentemente comecei a usar o FileHelpers e fiquei chocado com o quão ... ruim é. Por exemplo, a única maneira de mapear colunas em um csv para propriedades ... com licença, FIELDS, de um modelo é criar os campos na ordem das colunas . Eu não sei sobre você, mas eu não confiaria em uma peculiaridade do compilador para uma das considerações de design mais centrais da minha estrutura f8king.


2

SpreadsheetGear é incrível. Sim, é uma despesa, mas, comparada com as outras soluções, vale a pena o custo. É rápido, confiável, muito abrangente, e devo dizer que depois de usar este produto em meu trabalho de software em período integral por mais de um ano e meio, o suporte ao cliente é fantástico!


Difícil de justificar quando existem tantas maneiras simples e eficazes (de graça) de ler e escrever no Excel.
— Tipo anônimo

2

A solução que usamos, precisava:

  • Permitir leitura / gravação de arquivos produzidos no Excel
  • Seja rápido no desempenho (não como usar COMs)
  • Seja independente do MS Office (necessário para ser utilizável sem clientes com o MS Office instalado)
  • Seja gratuito ou de código aberto (mas desenvolvido ativamente)

Existem várias opções, mas descobrimos que o NPoi (porta .NET do projeto de código aberto Poi existente há muito tempo em Java ) é o melhor: http://npoi.codeplex.com/

Também permite trabalhar com os formatos de arquivo .doc e .ppt


2

Se são apenas dados tabulares. Eu recomendaria ajudantes de dados de arquivo de Marcos Melli, que podem ser baixados aqui .



1

você pode escrever uma planilha do Excel que carrega uma determinada planilha do Excel e a salva como CSV (em vez de fazê-lo manualmente).

então você pode automatizar isso a partir de c #.

e uma vez em csv, o programa c # pode grocá-lo.

(Além disso, se alguém solicitar que você programe no Excel, é melhor fingir que você não sabe como)

(edit: ah sim, rob e ryan estão certos)



1

Acabei de fazer um projeto de demonstração rápida que exigia o gerenciamento de alguns arquivos do Excel. O componente .NET do software GemBox era adequado para minhas necessidades. Tem uma versão gratuita com algumas limitações.

http://www.gemboxsoftware.com/GBSpreadsheet.htm


FYI: Eu tentei e não atendia à minha necessidade de poder ler um arquivo criptografado.
— Chad

1

O Pacote do Excel é um componente de código aberto (GPL) para leitura / gravação de arquivos do Excel 2007. Usei-o em um projeto pequeno, e a API é direta. Funciona apenas com XLSX (Excel 200 e), não com XLS.

O código-fonte também parece bem organizado e fácil de contornar (se você precisar expandir a funcionalidade ou corrigir problemas menores, como eu fiz).

Inicialmente, tentei a abordagem ADO.Net (cadeia de conexão do Excel), mas estava repleta de hackers desagradáveis ​​- por exemplo, se a segunda linha contiver um número, ela retornará ints para todos os campos da coluna abaixo e eliminará silenciosamente todos os dados isso não se encaixa.


1

Usamos o ClosedXML em sistemas bastante grandes.

  • Livre
  • Fácil de instalar
  • Codificação direta
  • Suporte muito responsivo
  • A equipe de desenvolvedores é extremamente aberta a novas sugestões. Muitas vezes, novos recursos e correções de erros são implementados na mesma semana

1

Take.ioA planilha fará esse trabalho para você, sem nenhum custo. Basta dar uma olhada nisso .


Esta é realmente uma ótima pequena biblioteca. Ele apenas converte tudo em Listas de Listas de strings, o que é bom para o tipo de trabalho que eu precisava.
— Drewmate

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.