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.