Чтение файлов Excel из C #


233

Существует ли бесплатная библиотека с открытым исходным кодом для чтения файлов Excel (.xls) непосредственно из программы на C #?

Это не должно быть слишком сложным, просто чтобы выбрать рабочий лист и прочитать данные в виде строк. До сих пор я использовал текстовую функцию «Экспорт в Юникод» в Excel и анализировал полученный файл (с разделителями табуляции), но я бы хотел исключить шаг вручную.

Ответы:


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"];

Это то, что я обычно использую. Это немного отличается, потому что я обычно вставляю AsEnumerable () при редактировании таблиц:

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

так как это позволяет мне использовать LINQ для поиска и построения структур из полей.

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"),
                    });

Если кажется, что Select в этом подходе пытается угадать тип данных столбца и навязать этот предполагаемый тип данных. Например, если у вас есть столбец с преимущественно двойными значениями, вам не понравится, когда вы передаете x.Field <string>, но ожидаете x.Field <double>. Это правда?
Кевин Ле - Khnle

1
Только что посмотрел на MSDN. Похоже, <T> используется только для попытки привести содержимое столбца к типу. В этом примере и просто приведение данных в столбцах к строкам. Если вам нужен double, вам нужно вызвать double.Parse (x.Field <string> ("Cost") или что-то в этом роде. Field - это метод расширения для DataRow, и похоже, что нет неуниверсальных версий.
Робин Робинсон

Замедляет ли добавление double.Parse к запросу Linq?
анонимный тип

23
Обратите внимание, что если вы читаете xlsx, вместо этого вам нужно использовать эту строку подключения:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
Андреас Греч

7
К сожалению, драйвер Jet.OLEDB не совместим с 64-битной версией; вам нужно будет переключиться на целевой x86, а не на любой процессор (если вы все еще хотите продолжить этот метод). В качестве альтернативы установите 64-разрядный драйвер ACE и измените строку подключения, чтобы использовать этот драйвер (как указано Андреасом) - microsoft.com/en-us/download/…
Дункан

83

Если это просто простые данные, содержащиеся в файле Excel, вы можете прочитать данные через ADO.NET. Смотрите строки подключения, перечисленные здесь:

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

-Ryan

Обновление: тогда вы можете просто прочитать лист через что-то вроде select * from [Sheet1$]


1
Этот путь, безусловно, самый быстрый.
StingyJack

17
Конечно, это не правда, Стинги. Вы должны просеять все данные и написать дрянной код БД (ручная работа над вашими моделями, сопоставление столбцов со свойствами, yadda yadda). Самый быстрый способ - позволить другим беднягам сделать это за вас . Вот почему люди используют фреймворки вместо того, чтобы писать все снизу вверх.

12
Бесполезный метод! Обрезает текстовые столбцы до 255 символов при чтении. Осторожно! Смотрите: stackoverflow.com/questions/1519288/… ACE engine делает то же самое!
Триынко

5
Имейте в виду, что для использования ADO.NET для чтения данных из exel необходимо установить Microsoft Access или Microsoft Access Database Engine Redistributable.
Зихотки

3
Драйвер также будет угадывать типы столбцов на основе первых нескольких строк. Если у вас есть столбец с тем, что выглядит как целые числа в первых строках, вы столкнетесь с ошибкой при попадании в нецелое число (например, число с плавающей точкой, строка)
Брайан Лоу

27

Подход ADO.NET является быстрым и легким, но в нем есть несколько особенностей, о которых вам следует знать, особенно в том, как обрабатываются типы данных.

Эта отличная статья поможет вам избежать некоторых распространенных ошибок: http://blog.lab49.com/archives/196


Вы ответили на мой вопрос (в форме комментария выше).
Кевин Ле - Khnle

22

Вот что я использовал для 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
лист не определен ... мне кажется немного странным после четкого определения всего остального.
Джереми Холовач

21

Как насчет Excel Data Reader?

http://exceldatareader.codeplex.com/

В производственной среде я использовал гнев для извлечения больших объемов данных из различных файлов Excel в SQL Server Compact. Это работает очень хорошо, и это довольно надежно.


2
Я буду второй Excel Data Reader; это также привело к созданию невероятно полезной библиотеки Excel Data Driven Tests, которая использует атрибут TestCaseSource в NUnit 2.5, чтобы сделать тесты, управляемые данными, с использованием электронных таблиц Excel до смешного легко. Просто знайте, что Resharper еще не поддерживает TestCaseSource, поэтому вы должны использовать NUnit Runner.
Дэвид Кивини

К сожалению, с этой библиотекой есть некоторые проблемы, с которыми мы только что столкнулись. Во-первых, у нас были некоторые валютные поля в виде дат. Во-вторых, происходит сбой, если в книге есть пустые листы. Итак, хотя это было очень легко интегрировать, сейчас мы переоцениваем, продолжать ли использовать эту библиотеку. Похоже, он не активно развивается.
Ian1971

Это также предполагает наличие некоторых необязательных элементов в файле xlsx, которые приводят к невозможности чтения данных, если они отсутствуют.
RichieHindle

У нас проблемы с файлами Excel, поступающими из служб отчетов SQL Server. Они просто не работают, если вы не откроете их и не сохраните их (даже не отредактированные). @RichieHindle: о каких дополнительных элементах вы говорите (надеюсь, это поможет мне с моими файлами SSRS Excel)?
Питер

@Peter: Я думаю, что это был отсутствующий <dimension>элемент в том, <worksheet>что доставляло мне неприятности.
RichieHindle

16

Вот код, который я написал на C # с использованием .NET 1.1 несколько лет назад. Не уверен, что это именно то, что вам нужно (и, возможно, не мой лучший код :)).

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;
        }
    }
}

Не могу согласиться с более черианским. Этому коду много лет ... еще до того, как я стал опытным с Resharper :)
hitec

2
Код некрасив, но он показывает, как получить имена листов, отлично!
Сэм

15

Koogra - это компонент с открытым исходным кодом, написанный на C #, который читает и записывает файлы Excel.


Больше не выглядит особенно активным по сравнению, скажем, с НКОИ
Дэвид Бертон


8

Некоторое время назад я много читал из файлов Excel в C #, и мы использовали два подхода:

  • COM API, где вы напрямую обращаетесь к объектам Excel и управляете ими через методы и свойства
  • Драйвер ODBC, который позволяет использовать Excel как базу данных.

Последний подход был намного быстрее: чтение большой таблицы с 20 столбцами и 200 строками заняло бы 30 секунд через COM и полсекунды через ODBC. Поэтому я бы порекомендовал подход с использованием базы данных, если вам нужны только данные.

Ура,

деревенщина


6

ExcelMapper - это инструмент с открытым исходным кодом ( http://code.google.com/p/excelmapper/ ), который можно использовать для чтения листов Excel в виде строго типизированных объектов. Он поддерживает форматы xls и xlsx.


6

Я хочу показать простой способ чтения файла xls / xlsx с помощью .NET. Я надеюсь, что следующее будет полезно для вас.

 private DataTable ReadExcelToTable (путь строки)    
 {

     // Строка соединения

     string connstring = "Provider = Microsoft.ACE.OLEDB.12.0; Источник данных =" + путь + "; Расширенные свойства = 'Excel 8.0; HDR = NO; IMEX = 1';";  
     // то же имя 
     // string connstring = Provider = Microsoft.JET.OLEDB.4.0; Источник данных = "+ путь + //"; Расширенные свойства = 'Excel 8.0; HDR = NO; IMEX = 1'; "; 

     использование (OleDbConnection conn = new OleDbConnection (connstring))
     {
        conn.Open ();
        // Получить имя всех листов
        DataTable sheetName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, new object [] {null, null, null, "Table"});  

        // Получить имя первого листа
        string firstSheetName = sheetName.Rows [0] [2] .ToString (); 

        //Строка запроса 
        строка sql = string.Format ("SELECT * FROM [{0}]", firstSheetName); 
        OleDbDataAdapter ada = новый OleDbDataAdapter (sql, connstring);
        DataSet set = new DataSet ();
        ada.Fill (комплект);
        вернуть set.Tables [0];   
   }
 }

Код взят из статьи: http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/ . Вы можете получить более подробную информацию от него.


2
Это было полезно, особенно часть о чтении имен листов.
martinstoeckli

4

Не бесплатно, но с последней версией Office есть очень хорошая автоматизация .Net API. (API долгое время существовал, но был неприятным COM). В коде можно делать все, что вам нужно / нужно, пока приложение Office остается скрытым фоновым процессом.


3
@ Anonymous-type Я прочитал вопрос и предлагал полезную альтернативу желаемой реализации OSS ... потому что, ну, я был почти уверен, что ничего не доступно. И, судя по принятому ответу, требование наличия Office не является проблемой.
xanadont

3

Извините, если я здесь вне базы, но разве это не для Office PIA ?


5
Да, но это может включать создание экземпляра Excel.Application, загрузку файла xls и т. Д. Если требуется просто прочитать некоторые данные из файла, тогда гораздо проще и гораздо проще использовать один из описанных методов ADO.NET. в других ответах.
Адам Ральф

Слишком медленно, используя Office PIA в качестве базовой линии, все остальное быстрее - даже просто используя массив Object, переданный из свойства .Value2. Который все еще использует PIA.
анонимный тип

3

В последнее время, частично, чтобы стать лучше в LINQ .... Я использовал API автоматизации Excel, чтобы сохранить файл в виде электронной таблицы XML, а затем обработать этот файл с помощью LINQ to XML.


Я подозреваю, что вы можете защитить его от Excel, но не от человека с компилятором ... как угодно ... это всего лишь байты.
Кенни

@gsvirdi, опубликуйте отдельный вопрос о безопасности файлов Excel, этот вопрос касается производительности.
анонимный тип

3

SpreadsheetGear for .NET - это совместимый с Excel компонент электронных таблиц для .NET. Вы можете увидеть, что говорят наши клиенты о производительности, в правой части страницы нашего продукта . Вы можете попробовать сами с помощью бесплатной, полнофункциональной оценки .


3

SmartXLS - это еще один компонент электронных таблиц Excel, который поддерживает большинство функций диаграмм Excel, механизмов формул и может читать / писать в формате openxml excel2007.



2

Я рекомендую библиотеку FileHelpers, которая является бесплатной и простой в использовании библиотекой .NET для импорта / экспорта данных из EXCEL, записей фиксированной длины или с разделителями в файлах, строках или потоках + еще.

Раздел документации ссылок на данные Excel http://filehelpers.sourceforge.net/example_exceldatalink.html


1
Я не откажусь от вас, но я недавно начал использовать FileHelpers и был шокирован тем, как ... это дерьмо. Например, единственный способ сопоставить столбцы в csv со свойствами ... извините, поля, модели - это создать поля в порядке столбцов . Я не знаю о вас, но я бы не стал полагаться на причуду компилятора для одного из самых главных соображений дизайна моей платформы f8king.


2

SpreadsheetGear - это круто. Да, это затраты, но по сравнению с этими другими решениями стоит затрат. Это быстро, надежно, очень полно, и я должен сказать, что после использования этого продукта в моей работе над программным обеспечением более полутора лет, их поддержка клиентов просто фантастическая!


Трудно оправдать, когда существует так много простых и эффективных способов (бесплатно) чтения и записи в Excel.
анонимный тип

2

Решение, которое мы использовали, требовало:

  • Разрешить чтение / запись файлов, созданных в Excel
  • Быть быстрым в производительности (не как использование COM)
  • Быть независимым от MS Office (необходимо использовать без клиентов, на которых установлен MS Office)
  • Быть свободным или открытым исходным кодом (но активно развиваться)

Есть несколько вариантов, но мы нашли NPoi (порт .NET для давно существующего проекта Java с открытым исходным кодом Poi ) лучшим: http://npoi.codeplex.com/

Также позволяет работать с форматами файлов .doc и .ppt.


2

Если это просто табличные данные. Я бы порекомендовал файловые помощники от Marcos Melli, которые можно скачать здесь .



1

Вы могли бы написать электронную таблицу Excel, которая загружает данную электронную таблицу Excel и сохраняет ее как CSV (вместо того, чтобы делать это вручную).

тогда вы можете автоматизировать это с C #.

и как только он в csv, программа c # может это сделать.

(также, если кто-то просит вас программировать в Excel, лучше всего делать вид, что вы не знаете как)

(править: ах, да, Роб и Райан оба правы)


1

Я знаю, что люди делали расширение Excel для этой цели.
Вы более или менее делаете кнопку в Excel с надписью «Экспорт в программу X», а затем экспортируете и отправляете данные в формате, который может прочитать программа.

http://msdn.microsoft.com/en-us/library/ms186213.aspx должно быть хорошим местом для начала.

Удачи


1

Просто сделал быстрый демонстрационный проект, который требовал управления некоторыми файлами Excel. Компонент .NET из программного обеспечения GemBox соответствовал моим потребностям. Имеется бесплатная версия с несколькими ограничениями.

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


К вашему сведению: я попробовал это, и это не соответствовало моей потребности прочитать зашифрованный файл.
Чад

1

Пакет Excel - это компонент с открытым исходным кодом (GPL) для чтения / записи файлов Excel 2007. Я использовал его в небольшом проекте, и API прост. Работает только с XLSX (Excel 200 &), но не с XLS.

Исходный код также выглядит хорошо организованным и его легко обойти (если вам нужно расширить функциональность или исправить мелкие проблемы, как я).

Сначала я попробовал подход ADO.Net (строка подключения Excel), но он был чреват неприятными взломами - например, если вторая строка содержит число, он вернет целые числа для всех полей в столбце ниже и тихо отбросит любые данные это не подходит


1

Мы используем ClosedXML в довольно больших системах.

  • Свободно
  • Прост в установке
  • Прямое кодирование
  • Очень отзывчивая поддержка
  • Команда разработчиков чрезвычайно открыта для новых предложений. Часто новые функции и исправления ошибок реализуются в течение одной недели

1

Take.ioЭлектронная таблица сделает эту работу за вас и бесплатно. Просто взгляните на это .


Это действительно отличная маленькая библиотека. Он просто конвертирует все в списки списков строк, что прекрасно подходит для той работы, для которой я нуждался.
Drewmate

0

Я просто использовал ExcelLibrary для загрузки электронной таблицы .xls в DataSet. Отлично сработало для меня.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.