Чтение файлов 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.