Читання файлів Excel із C #


233

Чи є безкоштовна або відкрита бібліотека для читання файлів Excel (.xls) безпосередньо з програми C #?

Не потрібно бути занадто фантазійним, просто вибрати робочий аркуш і прочитати дані як рядки. Поки що я використовував функцію Експортувати в Unicode текстову функцію 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>. Це правда?
Кевін Ле - Кнле

1
Просто подивився на MSDN. Схоже, що <T> просто використовується для спроби передати вміст у стовпці до типу. У цьому прикладі та просто введення даних у стовпці до рядків. Якщо ви хочете подвійний, вам потрібно буде зателефонувати double.Parse (x.Field <string> ("Вартість") або щось подібне. Поле - це метод розширення для DataRow, і схоже, що не існує загальних версій.
Робін Робінсон

Чи додає подвійний. Простий у запиті 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 та змініть рядок conn, щоб використовувати цей драйвер (як вказує Andreas) - microsoft.com/en-us/download/…
Duncan

83

Якщо це просто прості дані, що містяться у файлі Excel, ви можете прочитати дані через ADO.NET. Див. Переліки тут:

http://www.connectionstrings.com/?carrier=excel2007 або http://www.connectionstrings.com/?carrier=excel

-Райан

Оновлення: тоді ви можете просто прочитати робочий аркуш через щось подібне select * from [Sheet1$]


1
Цей шлях на сьогоднішній день найшвидший.
StingyJack

17
Звичайно, це неправда, Стінті. Вам потрібно просипати всі дані та писати хитрий код БД (вручну виготовити свої моделі, зіставити стовпці до властивостей, yadda yadda). Найшвидший спосіб - дозволити це зробити іншим бідним SOB для вас . Ось чому люди використовують рамки, а не пишуть все знизу вгору.

12
Нікчемний метод! Під час читання обрізає текстові стовпці до 255 символів. Остерігайся! Дивіться: stackoverflow.com/questions/1519288/… ACE двигун робить те саме!
Трайнко

5
Майте на увазі, що для використання ADO.NET для зчитування даних з exel потрібен встановлений перерозподільний доступ Microsoft Access або Microsoft Access Database Engine
zihotki

3
Водій також вгадає типи стовпців на основі перших кількох рядків. Якщо у вас є стовпець із схожими на цілі числа в перших рядках, ви зіткнетеся з помилкою, коли потрапите на не ціле число (наприклад, float, рядок)
Brian Low

27

Підхід ADO.NET швидкий і простий, але він має кілька примх, про які слід пам’ятати, особливо щодо способів обробки даних.

Ця чудова стаття допоможе вам уникнути деяких загальних підводних каменів: http://blog.lab49.com/archives/196


Ви відповіли на моє запитання (у формі коментаря вище).
Кевін Ле - Кнле

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?

http://exceldatareader.codeplex.com/

Я використовував у цьому гнів у виробничих умовах, щоб перетягувати велику кількість даних з різних файлів Excel у SQL Server Compact. Він працює дуже добре і досить надійний.


2
Я другий зчитувач даних Excel; це також призвело до надзвичайно корисної бібліотеки тестів, керованих даними Excel, яка використовує атрибут TestCaseSource NUnit 2.5 для того, щоб зробити керовані даними тести за допомогою електронних таблиць Excel смішно простими. Будьте обережні, що Resharper ще не підтримує TestCaseSource, тому вам доведеться використовувати бігун NUnit.
David Keaveny

На жаль, є деякі проблеми з цією бібліотекою, з якими ми щойно стикалися. По-перше, у нас були деякі валютні поля, які виходили як дати. По-друге, це збій, якщо в робочій книжці є порожні аркуші. Отже, хоча це було дуже легко інтегрувати, ми зараз переоцінюємо, чи варто продовжувати користуватися цією бібліотекою. Схоже, це активно не розвивається.
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
Код некрасивий, але він показує, як отримати назви аркушів, чудово!
Сем



8

Я багато читав з файлів Excel в C # деякий час тому, і ми застосували два підходи:

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

Останній підхід був набагато швидшим: читання великої таблиці з 20 стовпцями та 200 рядками зайняло б 30 секунд через COM, і пів секунди через ODBC. Тому я б рекомендував підхід до бази даних, якщо вам потрібні лише дані.

Ура,

Карл



6

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

 приватний DataTable ReadExcelToTable (рядок шлях)    
 {

     // Рядок з'єднання

     string connstring = "Постачальник = Microsoft.ACE.OLEDB.12.0; Джерело даних =" + шлях + "; Розширені властивості = 'Excel 8.0; HDR = НЕ; IMEX = 1';";  
     // однойменна назва 
     // string connstring = Провайдер = Microsoft.JET.OLEDB.4.0; Джерело даних = "+ шлях + //"; Розширені властивості = 'Excel 8.0; HDR = НЕ; IMEX = 1'; "; 

     використовуючи (OleDbConnection conn = новий OleDbConnection (connstring))
     {
        conn.Open ();
        // Отримати назву всіх таблиць
        DataTable listeName = conn.GetOleDbSchemaTable (OleDbSchemaGuid.Tables, новий об’єкт [] {null, null, null, "Table"});  

        // Отримати назву першого листа
        рядок firstSheetName = listeName.Rows [0] [2] .ToString (); 

        // Рядок запиту 
        рядок sql = string.Format ("SELECT * FROM [{0}]", firstSheetName); 
        OleDbDataAdapter ada = новий OleDbDataAdapter (sql, connstring);
        Набір даних = новий DataSet ();
        ada.Fill (набір);
        повернутий набір.Таблиці [0];   
   }
 }

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


2
Це було корисно, особливо частина про читання назви аркушів.
martinstoeckli

4

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


3
@ Анонімний тип я прочитав запитання і запропонував корисну альтернативу бажаній реалізації OSS ... тому що я був майже впевнений, що нічого немає в наявності. І, судячи з прийнятої відповіді, вимога встановити Office не є проблемою.
xanadont

3

Пробачте мене, якщо я тут поза межами бази, але чи не для цього призначено службове агентство PIA ?


5
Так, але це передбачає створення екземпляра Excel.Application, завантаження файлу xls тощо. Якщо вимога полягає лише в тому, щоб прочитати деякі дані з файлу, то використовувати один з описаних методів ADO.NET набагато простіше і набагато легше. в інших відповідях.
Адам Ральф

Занадто повільно, використовуючи Office PIA в якості базової лінії, все інше відбувається швидше - навіть просто використання масиву Object, переданого від властивості .Value2. Який досі використовує PIA.
Анонімний тип

3

Останнім часом частково для покращення роботи в LINQ .... Я використовував API автоматизації Excel, щоб зберегти файл як електронну таблицю XML, а потім отримати цей файл, використовуючи LINQ в XML.


Я б підозрював, що ви можете захистити його від Excel, але не від людини з компілятором ... як і все ... це просто байти.
kenny

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

3

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


3

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



2

Я рекомендую бібліотеку FileHelpers, яка є вільною і простою у використанні .NET бібліотекою для імпорту / експорту даних з EXCEL, фіксованої довжини або обмежених записів у файлах, рядках або потоках + Більше.

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


1
Я не підведу вас, але нещодавно я почав використовувати FileHelpers і був шокований тим, наскільки ... шалено це. Наприклад, єдиний спосіб зіставити стовпці в csv до властивостей ... вибачте, FIELDS моделі - створити поля в порядку стовпців . Я не знаю про вас, але я б не покладався на химерність компілятора для однієї з найважливіших міркувань дизайну моєї рамки f8king.


2

SpreadsheetGear є приголомшливим. Так, це витрата, але в порівнянні з подвійним виглядом з цими іншими рішеннями, це вартує витрат. Це швидко, надійно, дуже всебічно, і я повинен сказати, що після використання цього продукту в моїй програмі повного робочого дня протягом півтора року, їх підтримка клієнтів є фантастичною!


Важко виправдати, коли існує стільки простих та ефективних способів (безкоштовно) читання та запису в Excel.
Анонімний тип

2

Рішення, яке ми використовували, потрібно було:

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

Є кілька варіантів, але ми визнали, що NPoi (.NET порт давно існуючого проекту Java з відкритим кодом Poi ) є найкращим: http://npoi.codeplex.com/

Це також дозволяє працювати з форматами файлів .doc та .ppt


2

Якщо це просто табличні дані. Я б порекомендував помічників файлових даних від Маркоса Меллі, які можна завантажити тут .



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


FYI: Я спробував це, і це не відповідало моїй потребі вміти читати зашифрований файл.
Чад

1

Пакет Excel - це компонент з відкритим кодом (GPL) для читання / запису файлів Excel 2007. Я використовував це в невеликому проекті, а API - це просто. Працює лише з XLSX (Excel 200 &), а не з XLS.

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

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


1

Ми використовуємо ClosedXML у досить великих системах.

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

1

Take.ioЕлектронна таблиця зробить цю роботу за вас, і безкоштовно. Просто погляньте на це .


Це дійсно чудова маленька бібліотека. Він просто перетворює все у списки рядків рядків, що просто чудово для роботи, яка мені потрібна.
Drewmate

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.