Как создать файл Excel (.XLS и .XLSX) в C # без установки Microsoft Office?

1894

Как создать электронную таблицу Excel с C #, не требуя установки Excel на компьютере, на котором выполняется код?

mistrmark
источник
"... без установки MS Office?" часть вопроса звучит очень непрофессионально. Вы можете создать любой тип файла из программы на C # ( одним из которых является файл xlsили xlsx). Не обязательно, чтобы на вашем компьютере была программа, которая может читать ее (скажем, двоичную).
Майк
30
@Mike Часть «не требующая установки Excel» не имеет ничего общего с профессионализмом. Это о зависимостях. Первоначальный текст вопроса был сформулирован так: «В идеале, я хотел бы, чтобы с открытым исходным кодом, поэтому мне не нужно было добавлять какие-либо сторонние зависимости в мой код, и я хотел бы избежать использования Excel непосредственно для создания файла (используя OLE Автоматизация.) « К сожалению, вопрос был резко упрощен.
Тони
5
Предполагая, что вы пытаетесь сделать что-то без библиотеки или внешнего кода, я не могу говорить о файле xls, но о файлах xlsx, почему бы не начать с того, чтобы взять существующий, переименовать его в zip-файл и изучить содержимое? Немного обратного инжиниринга расскажет вам совсем немного. Существует несколько разных XML-файлов и файлов Rels в различных папках и подпапках. Попробуйте изучить это и посмотреть, можете ли вы это повторить, или посмотрите, можете ли вы найти документацию по различным пространствам имен / схемам xml.
Александр Райан Баггетт
@AlexanderRyanBaggett Это было очень полезно! Столкнулся с этим постом, работая над автоматическим созданием отчетов и изучением документов в виде zip-архива, который дает представление о том, что входит в создание файла документа.
SentientFlesh

Ответы:

1056

Вы можете использовать библиотеку под названием ExcelLibrary. Это бесплатная библиотека с открытым исходным кодом, размещенная в Google Code:

ExcelLibrary

Это выглядит как порт PHP ExcelWriter, который вы упомянули выше. Он пока не будет писать в новый формат .xlsx, но они работают над добавлением этой функциональности в.

Это очень просто, маленький и простой в использовании. Кроме того, он имеет DataSetHelper, который позволяет вам использовать DataSets и DataTables для удобной работы с данными Excel.

ExcelLibrary, кажется, все еще работает только для более старого формата Excel (файлы .xls), но может добавить поддержку в будущем для новых форматов 2007/2010.

Вы также можете использовать EPPlus , который работает только для файлов формата Excel 2007/2010 (файлы .xlsx). Есть также NPOI, который работает с обоими.

Есть несколько известных ошибок с каждой библиотекой, как отмечено в комментариях. В целом, EPPlus кажется лучшим выбором с течением времени. Кажется, что он также более активно обновляется и документируется.

Кроме того, как отмечает @ АртёмЦарионов ниже, EPPlus имеет поддержку сводных таблиц, а ExcelLibrary может иметь некоторую поддержку ( проблема сводных таблиц в ExcelLibrary )

Вот несколько ссылок для краткого справочника:
ExcelLibrary - GNU Lesser GPL
EPPlus - GNU Lesser General Public License (LGPL)
NPOI - Apache License

Вот пример кода для ExcelLibrary:

Вот пример получения данных из базы данных и создания из нее рабочей книги. Обратите внимание, что код ExcelLibrary - это одна строка внизу:

//Create the data set and table
DataSet ds = new DataSet("New_DataSet");
DataTable dt = new DataTable("New_DataTable");

//Set the locale for each
ds.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;
dt.Locale = System.Threading.Thread.CurrentThread.CurrentCulture;

//Open a DB connection (in this example with OleDB)
OleDbConnection con = new OleDbConnection(dbConnectionString);
con.Open();

//Create a query and fill the data table with the data from the DB
string sql = "SELECT Whatever FROM MyDBTable;";
OleDbCommand cmd = new OleDbCommand(sql, con);
OleDbDataAdapter adptr = new OleDbDataAdapter();

adptr.SelectCommand = cmd;
adptr.Fill(dt);
con.Close();

//Add the table to the data set
ds.Tables.Add(dt);

//Here's the easy part. Create the Excel worksheet from the data set
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", ds);

Создать файл Excel так просто. Вы также можете вручную создавать файлы Excel, но вышеперечисленные функции меня поразили.

Майк Уэбб
источник
247
ExcelLibrary был заменен исключительным EPPlus - epplus.codeplex.com . Ян регулярно обновляет его. Я использовал его, и это один из лучших проектов с открытым исходным кодом, с которыми мы работали.
Отметить
3
Следует отметить, что ExcelLibrary имеет много проблем с производительностью при работе с большими наборами данных (более 5000 строк с большим количеством столбцов). В настоящее время ведется серьезная модификация базы кода на работе, чтобы мы могли использовать ее в проекте.
rossisdead
EPPlus кажется гораздо менее глючным, чем ExcelLibrary, НО это GPL и, следовательно, только решение для проектов с открытым исходным кодом.
Сет
6
Что насчет ClosedXML ? Я могу оказаться полезным в ваших проектах.
Амадеус Санчес
589

Если вы довольны форматом xlsx, попробуйте мой проект GitHub, EPPlus . Все началось с исходного кода из ExcelPackage, но сегодня это полное переписывание. Он поддерживает диапазоны, стилизацию ячеек, диаграммы, фигуры, изображения, именованные диапазоны, автофильтр и многое другое.

Jan Källman
источник
77
Лицензия теперь LGPL, примечания к выпуску здесь: epplus.codeplex.com/releases/view/79802
Simon D
13
Примеры были полезны. Мне удалось сменить код с использования библиотеки взаимодействия Microsoft (ужасно медленно) на эту библиотеку (версия 4.x) за пару часов. Мой бенчмарк пишет файл с двумя вкладками и около 750 000 ячеек. Использование MS взаимодействия заняло 13 минут. Использование EPPlus заняло 10 секунд, примерно 80-кратное ускорение. Очень счастлив!
Павел Чернох
3
Для ясности в этой теме LGPL позволяет связывать программное обеспечение без возникновения какой-либо инфицированной части GPL. Вам нужно только открыть исходные изменения, внесенные вами в ClosedXml, или, если вы непосредственно поместите исходный код (в отличие от ссылки на сборки ClosedXml) внутри своего приложения, вам нужно будет открыть исходное приложение.
Крис Марисик,
4
@Paul Chernoch: Мы заполняем большие листы Excel очень быстро. Секрет в том, чтобы сделать массовое обновление. Создайте блок object [,], заполните его, а затем запишите эту матрицу в Excel одновременно: excelWorksheet.get_Range (range) .Value2 = block;
Марк Мекетон
2
Похоже, что лицензия переходит от LGPL к лицензии Polyform Noncommercial 1.0.0
Лука,
175

А как насчет использования Open XML SDK 2.0 для Microsoft Office?

Несколько преимуществ:

  • Не требует установленного Office
  • Сделано Microsoft = достойная документация MSDN
  • Просто одна .Net DLL для использования в проекте
  • SDK поставляется со многими инструментами, такими как diff, validator и т. Д.

Ссылки:

Sogger
источник
3
Важно отметить, что DLL для этого составляет чуть более 5 МБ и ограничивается форматами Office 2007. Но, безусловно, самое простое и быстрое решение, которое работает для меня.
Джош Браун
18
Просто один на один, версия v2.5 вышла и может быть загружена здесь .
Snuffleupagus
10
SDK моделирует XML в классы, так что каждый тег XML сопоставляется с тегом, а затем необходимо правильно построить иерархию классов (каждый экземпляр имеет коллекцию дочерних экземпляров / тегов). Это означает, что вы должны знать структуру XML файла Excel, что очень сложно. Намного проще использовать оболочку, такую ​​как EPPlus, упомянутую выше, что упрощает работу.
Цахи Ашер
2
Отличный образец Microsoft Open XML SDK - Open XML Writer можно найти по адресу polymathprogrammer.com/2012/08/06/… Или см. Решение Stack Overflow stackoverflow.com/questions/11370672/…
Грег
4
Я нашел Microsoft Open XML SDK Open XML Writer, чтобы быть отличным. Используя приведенные выше решения (особенно пример Винсента Тома (Poly Math)), легко создать устройство записи, которое транслирует большие наборы данных и записывает записи способом, аналогичным и не слишком сложным по сравнению с тем, что вы делаете для CSV; но вы вместо этого пишете XML. Открытый XML - это образ мыслей, который Microsoft рассматривает в своих новых форматах Office. И вы всегда можете переименовать их из файлов .xslx в .zip, если вам захочется заглянуть в их содержимое XML.
Грег
167

Я успешно использовал следующие проекты с открытым исходным кодом:

  • ExcelPackage для форматов OOXML (Office 2007)

  • NPOI для формата .XLS (Office 2003). NPOI 2.0 (бета-версия) также поддерживает XLSX.

Посмотрите на мои сообщения в блоге:

Создание электронных таблиц Excel .XLS и .XLSX в C #

NPOI с таблицей Excel и динамической диаграммой

Leniel Maccaferri
источник
6
Примечание к NPOI - ссылки на строки и столбцы начинаются с нуля. Хорошо работает для заполнения существующего шаблона.
Джон М
108

Вы можете использовать OLEDB для создания и управления файлами Excel. Проверьте это: чтение и запись в Excel с использованием OLEDB .

Типичный пример:

using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\temp\\test.xls;Extended Properties='Excel 8.0;HDR=Yes'"))
{
  conn.Open();
  OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Sheet1] ([Column1] string, [Column2] string)", conn);
  cmd.ExecuteNonQuery();
}

РЕДАКТИРОВАТЬ - Еще несколько ссылок:

Panos
источник
4
Может кто-нибудь подтвердить, работает ли это при работе в x64? Я уверен, что Jet работает, только если ваше приложение скомпилировано или работает в 32-битном режиме.
Ламар
2
Я только что проверил это соединение, и оно не установилось на Windows Server 2008 R2 x64 RC. Кажется, нужно установить драйвер системы Office 2007: компоненты для подключения к данным [ microsoft.com/downloads/…
Крис Ричнер,
25
Будьте очень осторожны с этим - это большой уродливый клочок (например, иногда он угадывает тип столбца и отбрасывает все данные, которые не подходят).
ДБКК
9
Нужно быть очень осторожным при использовании этого метода. Я нашел это очень ненадежным для данных, которые не в идеальном формате.
Кенни Манн
9
Как человек, который должен был использовать OleDb в большом проекте, я говорю «ОСТАЙСЯ ОТ ЭТОГО!» Иногда он не может получить значение ячейки только потому, что не может понять формат. У него нет операции удаления. Он работает совершенно иначе и непредсказуемо даже при малейшей смене провайдера. Я бы сказал, пойти на проверенное коммерческое решение.
Caner Öncü
80

Коммерческое решение, SpreadsheetGear для .NET сделает это.

Вы можете увидеть живые образцы ASP.NET (C # и VB) здесь и скачать ознакомительную версию здесь .

Отказ от ответственности: я владею SpreadsheetGear LLC

Джо Эриксон
источник
10
У вас отличный продукт, но я думаю, что многие люди ждут бесплатных решений. Это может объяснить отрицательные голоса.
md1337
65

Несколько вариантов, которые я использовал:

Если XLSX является обязательным: ExcelPackage - хорошее начало, но затихло, когда разработчик прекратил работу над ним. Оттуда взял ExML и добавил несколько функций. ExML не плохой вариант, я все еще использую его на нескольких производственных сайтах.

Однако для всех моих новых проектов я использую NPOI , порт .NET Apache POI . NPOI 2.0 (Alpha) также поддерживает XLSX.

Nate
источник
Будьте осторожны с ExcelPackage, если вам нужна поддержка XLS. Мне было трудно с этим и в конечном итоге переключился на ExcelLibrary.
Джереми
Определенно верно. ExcelPackage / ExML - хороший вариант, только если вам нужна поддержка XLSX.
Нат
5
Обратите внимание, что ExcelPackage имеет преемника: EPPlus ( epplus.codeplex.com ), который поддерживает XLSX. По сравнению с NPOI, например, меня беспокоит только производительность, например, когда столбцов много.
Pragmateek
63

Чрезвычайно легким вариантом может быть использование таблиц HTML. Просто создайте теги head, body и table в файле и сохраните его как файл с расширением .xls. Существуют специфические атрибуты Microsoft, которые можно использовать для оформления вывода, включая формулы.

Я понимаю, что вы можете не кодировать это в веб-приложении, но вот пример компоновки файла Excel через таблицу HTML. Эту технику можно использовать, если вы кодируете консольное приложение, настольное приложение или службу.

забытой точки с запятой
источник
6
Он такой специальный, но он работает (не говоря уже о выдаче предупреждения об открытии) и настолько прост, что заслуживает того, чтобы найти решение. Хотя только для того, чтобы показать, что вы можете экспортировать файл Excel :))
Лука Рамишвили
3
Это решение отлично сработало для меня, только заметьте, что вы не можете использовать расширение .xlsx
Jill
Некоторые сотрудники моей организации не могут открывать файлы Excel, созданные таким образом в Office 2010 и более поздних версиях. Не знаю, в чем проблема, но мне пришлось свернуть мою собственную реализацию OpenXML. (см. ответ Соггера)
Кристен Хаммак
49

Если вы создаете файлы Excel 2007/2010, попробуйте этот проект с открытым исходным кодом: https://github.com/closedxml/closedxml

Он предоставляет объектно-ориентированный способ манипулировать файлами (аналогично VBA), не сталкиваясь с трудностями XML-документов. Он может использоваться любым языком .NET, таким как C # и Visual Basic (VB).

ClosedXML позволяет создавать файлы Excel 2007/2010 без приложения Excel. Типичный пример - создание отчетов Excel на веб-сервере:

var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell("A1").Value = "Hello World!";
workbook.SaveAs("HelloWorld.xlsx");
Armfoot
источник
9
Я попытался использовать это в проекте, который создает довольно большие листы Excel. Отличная библиотека, но крайне плохая производительность. Я только что сделал сравнение для проекта, над которым я работаю: ClosedXML (v 0.53.3) занял 92 489 мс, а EPPlus (v 2.9.03, для тестирования - мы не можем использовать, потому что это GPL) - 16 500 мс.
Друид
1
@ Друид - лицензия LGPL, при условии, что вы не изменяете исходный код на ClosedXML; вы можете бесплатно использовать epplus.codeplex.com/license
Крис Марисик,
47

Возможно, вы захотите проверить классы взаимодействия, доступные в C # (например, Microsoft.Office.Interop.Excelвы говорите, что нет OLE (что это не так), но классы взаимодействия очень просты в использовании. Ознакомьтесь с документацией по C # здесь (Interop for Excel начинается с стр. 1072 C # PDF).

Вы можете быть впечатлены, если не попробовали их.

Пожалуйста, обратите внимание на позицию Microsoft по этому вопросу:

В настоящее время Microsoft не рекомендует и не поддерживает автоматизацию приложений Microsoft Office из любых необслуживаемых, неинтерактивных клиентских приложений или компонентов (включая ASP, ASP.NET, DCOM и NT Services), поскольку Office может демонстрировать нестабильное поведение и / или или тупик, когда Office работает в этой среде.

GEOCHET
источник
6
Но вы должны убедиться, что вы утилизируете все вручную, иначе вы
потеряете
8
@ Рики Б: Кроме того, по моему опыту с взаимодействием, он использует Excel. Каждый раз, когда мы использовали его, если Excel не был установлен на машине, мы получали исключения COM.
MagicKat,
1
С OLE, даже с очень осторожными утилизациями, это в конечном счете приводит к утечке памяти или сбоям. Это, возможно, нормально для посещаемых приложений / рабочих станций, но для серверов не рекомендуется (MS имеет KB с указанием этого). Для нашего сервера мы просто перезагружаем его каждую ночь. Опять же, это работает хорошо.
Дженнифер Зуак
11
@ Geoffrey: ах, ладно, вы заставите меня работать на него :) -> support.microsoft.com/kb/257757 В настоящее время Microsoft не рекомендует и не поддерживает автоматизацию приложений Microsoft Office из любых оставленных без присмотра интерактивное клиентское приложение ...
Дженнифер Зуак
4
Я прихожу к этой дискуссии после более чем недели борьбы за взаимодействие, и если ваши потребности не очень просты, это не сработает. Поддержка форматирования вашей электронной таблицы ужасна, что, возможно, и является причиной создания файла .xls, а не просто плоского файла .csv. Например, вы пытались вывести более 911 символов в ячейку, или вы пытались установить ширину объединенных ячеек согласованным образом? У меня есть, и я не могу сказать вам, как сильно я ненавижу эту чушь сейчас ... Сделайте себе одолжение и воспользуйтесь одной из бесплатных библиотек, упомянутых в этом обсуждении.
md1337
34

Вот совершенно бесплатно C # библиотека, которая позволяет экспортировать из DataSet, DataTableили List<>в подлинном Excel 2007 .xlsx файл, используя библиотеки OpenXml:

http://mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm

Полный исходный код предоставляется - бесплатно - вместе с инструкциями и демонстрационным приложением.

После добавления этого класса в ваше приложение вы можете экспортировать свой DataSet в Excel всего за одну строку кода:

CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");

Это не намного проще, чем это ...

И это даже не требует присутствия Excel на вашем сервере.

Майк Гледхилл
источник
1
Это кажется немного вводящим в заблуждение, поскольку вы просите пожертвование, чтобы получить все функции.
UrbanEsc
Это отчасти верно: совершенно бесплатная версия сгенерирует идеальный файл .xlsx для вас, и весь исходный код предоставлен. Если вы пожертвуете 10 или более долларов одной из этих двух благотворительных организаций (из которых я абсолютно ничего не получу), тогда вы получите «лучшую» версию, показывающую, как выполнять форматирование, даты и т. Д. Учитывая стоимость сторонних продуктов, я считаю, пожертвование 10 долларов на благое дело вместо этого стоит того!
Майк Гледхилл
23

Возможно, вы захотите взглянуть на GemBox.Spreadsheet .

У них есть бесплатная версия со всеми функциями, но не более 150 строк на листе и 5 листов на книгу, если это соответствует вашим потребностям.

Мне еще не приходилось пользоваться им, но выглядит интересно.

ManiacZX
источник
21

Syncfusion Essential XlsIO может сделать это. Он не зависит от Microsoft Office, а также имеет специальную поддержку для различных платформ.

Пример кода:

//Creates a new instance for ExcelEngine.
ExcelEngine excelEngine = new ExcelEngine();
//Loads or open an existing workbook through Open method of IWorkbooks
IWorkbook workbook = excelEngine.Excel.Workbooks.Open(fileName);
//To-Do some manipulation|
//To-Do some manipulation
//Set the version of the workbook.
workbook.Version = ExcelVersion.Excel2013;
//Save the workbook in file system as xlsx format
workbook.SaveAs(outputFileName);

Весь набор средств управления предоставляется бесплатно через программу лицензий сообщества, если вы соответствуете требованиям (доход менее 1 миллиона долларов США). Примечание: я работаю на Syncfusion.

Davis Jebaraj
источник
18

Хорошо,

Вы также можете использовать стороннюю библиотеку, такую ​​как Aspose .

Преимущество этой библиотеки в том, что она не требует установки Excel на вашем компьютере, что было бы идеально в вашем случае.

Дими Тулакис
источник
Чтобы быть более точным, вы можете использовать Aspose.Cells для .NET для создания файлов Excel (XLS, XLSX) в вашем приложении .NET.
Шахзад Латиф
9
Да, вы можете, если не возражаете заплатить минимальный лицензионный сбор в размере 999 долларов. Попробуйте библиотеку MikesKnowledgeBase ... которая на $ 999 дешевле, чем эта !!
Майк Гледхилл
17

OpenXML также является хорошей альтернативой, которая помогает избежать установки MS Excel на сервере. Open XML SDK 2.0, предоставляемый Microsoft, упрощает задачу управления пакетами Open XML и базовыми элементами схемы Open XML внутри пакета. Интерфейс прикладного программирования (XML) Open XML включает в себя множество общих задач, которые разработчики выполняют с пакетами Open XML.

Проверьте это OpenXML: Альтернатива, которая помогает избежать установки MS Excel на сервере

Сачин Дхир
источник
17

Доступны различные библиотеки Office 2003 XML для небольших файлов Excel. Тем не менее, я считаю большой размер большой рабочей книги, сохраненной в формате XML, проблемой. Например, рабочая книга, с которой я работаю, будет 40 МБ в новом (и по общему мнению, более плотно упакованном) формате XLSX и станет XML-файлом размером 360 МБ.

Насколько мне показало мое исследование, есть два коммерческих пакета, которые позволяют выводить файлы в более старые двоичные форматы. Они есть:

Ни один не дешев (500 долларов США и 800 долларов США соответственно, я думаю). но оба работают независимо от самого Excel.

Что мне было бы интересно, так это модуль вывода в Excel для OpenOffice.org. Интересно, можно ли их портировать с Java на .Net.

биоцинк
источник
Этот работает как на .net и Java, и не дорогой. SmartXLS smartxls.com
Liya
15

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

Это коммерческий продукт, но вы получите полный источник, если купите его. Так что, я полагаю, вы могли бы скомпилировать его в свою сборку, если бы вы действительно этого хотели. В противном случае это всего лишь одна дополнительная сборка для xcopy - без настройки, установки или чего-то подобного.

Я не думаю, что вы найдете какой-либо способ сделать это без сторонних библиотек, так как .NET Framework, очевидно, не имеет встроенной поддержки для него, а OLE Automation - это целый мир боли.

EMP
источник
15

Я написал простой код для экспорта набора данных в Excel без использования объекта Excel с помощью System.IO.StreamWriter.

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

public static void exportToExcel(DataSet source, string fileName)
{
        const string endExcelXML = "</Workbook>";
        const string startExcelXML = "<xml version>\r\n<Workbook " +
                 "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
                 " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
                 "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
                 "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
                 "office:spreadsheet\">\r\n <Styles>\r\n " +
                 "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
                 "<Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>" +
                 "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
                 "\r\n <Protection/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
                 "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
                 "<Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
                 " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"Decimal\">\r\n <NumberFormat " +
                 "ss:Format=\"0.0000\"/>\r\n </Style>\r\n " +
                 "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
                 "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
                 "ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
                 "ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n " +
                 "</Styles>\r\n ";
        System.IO.StreamWriter excelDoc = null;
        excelDoc = new System.IO.StreamWriter(fileName);

        int sheetCount = 1;
        excelDoc.Write(startExcelXML);
        foreach (DataTable table in source.Tables)
        {
            int rowCount = 0;
            excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
            excelDoc.Write("<Table>");
            excelDoc.Write("<Row>");
            for (int x = 0; x < table.Columns.Count; x++)
            {
                excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
                excelDoc.Write(table.Columns[x].ColumnName);
                excelDoc.Write("</Data></Cell>");
            }
            excelDoc.Write("</Row>");
            foreach (DataRow x in table.Rows)
            {
                rowCount++;
                //if the number of rows is > 64000 create a new page to continue output
                if (rowCount == 64000)
                {
                    rowCount = 0;
                    sheetCount++;
                    excelDoc.Write("</Table>");
                    excelDoc.Write(" </Worksheet>");
                    excelDoc.Write("<Worksheet ss:Name=\"" + table.TableName + "\">");
                    excelDoc.Write("<Table>");
                }
                excelDoc.Write("<Row>"); //ID=" + rowCount + "
                for (int y = 0; y < table.Columns.Count; y++)
                {
                    System.Type rowType;
                    rowType = x[y].GetType();
                    switch (rowType.ToString())
                    {
                        case "System.String":
                            string XMLstring = x[y].ToString();
                            XMLstring = XMLstring.Trim();
                            XMLstring = XMLstring.Replace("&", "&");
                            XMLstring = XMLstring.Replace(">", ">");
                            XMLstring = XMLstring.Replace("<", "<");
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                           "<Data ss:Type=\"String\">");
                            excelDoc.Write(XMLstring);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DateTime":
                            //Excel has a specific Date Format of YYYY-MM-DD followed by  
                            //the letter 'T' then hh:mm:sss.lll Example 2005-01-31T24:01:21.000
                            //The Following Code puts the date stored in XMLDate 
                            //to the format above
                            DateTime XMLDate = (DateTime)x[y];
                            string XMLDatetoString = ""; //Excel Converted Date
                            XMLDatetoString = XMLDate.Year.ToString() +
                                 "-" +
                                 (XMLDate.Month < 10 ? "0" +
                                 XMLDate.Month.ToString() : XMLDate.Month.ToString()) +
                                 "-" +
                                 (XMLDate.Day < 10 ? "0" +
                                 XMLDate.Day.ToString() : XMLDate.Day.ToString()) +
                                 "T" +
                                 (XMLDate.Hour < 10 ? "0" +
                                 XMLDate.Hour.ToString() : XMLDate.Hour.ToString()) +
                                 ":" +
                                 (XMLDate.Minute < 10 ? "0" +
                                 XMLDate.Minute.ToString() : XMLDate.Minute.ToString()) +
                                 ":" +
                                 (XMLDate.Second < 10 ? "0" +
                                 XMLDate.Second.ToString() : XMLDate.Second.ToString()) +
                                 ".000";
                            excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                            excelDoc.Write(XMLDatetoString);
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Boolean":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                        "<Data ss:Type=\"String\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Int16":
                        case "System.Int32":
                        case "System.Int64":
                        case "System.Byte":
                            excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                    "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.Decimal":
                        case "System.Double":
                            excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                                  "<Data ss:Type=\"Number\">");
                            excelDoc.Write(x[y].ToString());
                            excelDoc.Write("</Data></Cell>");
                            break;
                        case "System.DBNull":
                            excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                  "<Data ss:Type=\"String\">");
                            excelDoc.Write("");
                            excelDoc.Write("</Data></Cell>");
                            break;
                        default:
                            throw (new Exception(rowType.ToString() + " not handled."));
                    }
                }
                excelDoc.Write("</Row>");
            }
            excelDoc.Write("</Table>");
            excelDoc.Write(" </Worksheet>");
            sheetCount++;
        }


        excelDoc.Write(endExcelXML);
        excelDoc.Close();
    }
Harsha.Vaswani
источник
1
Как говорится в статье, это XML, который Excel будет читать, а не просто файл XLS, что означает, что он может работать только в Excel, а не в других программах, которые читают электронные таблицы. Но это, вероятно, лучше, чем ответы в эквивалентной таблице HTML здесь!
Руп
Поддерживает xlsx ? OpenXML ?
Kiquenet
14

Просто хочу добавить еще одну ссылку на стороннее решение, которое напрямую решает вашу проблему: http://www.officewriter.com

(Отказ от ответственности: я работаю на SoftArtisans, компанию, которая делает OfficeWriter)

Eisbaer
источник
12

Вот способ сделать это с помощью LINQ to XML, дополненный примером кода:

Быстрый импорт и экспорт данных Excel с помощью LINQ to XML

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

(Также, конечно, это VB .NET, а не C #, но вы всегда можете изолировать материал VB .NET в своем собственном проекте, чтобы использовать XML-литералы, и делать все остальное в C #.)

оборота Киралесса
источник
12

Некоторые сторонние поставщики компонентов, такие как Infragistics или Syncfusion, предоставляют очень хорошие возможности экспорта в Excel, которые не требуют установки Microsoft Excel.

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

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

Ранее я принимал участие в проектах, которые пытались использовать автоматизацию на стороне сервера в пакете Microsoft Office. Основываясь на этом опыте, я настоятельно рекомендую против такого подхода.

Симен С
источник
12
public class GridViewExportUtil
{
    public static void Export(string fileName, GridView gv)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.AddHeader(
            "content-disposition", string.Format("attachment; filename={0}", fileName));
        HttpContext.Current.Response.ContentType = "application/ms-excel";

        using (StringWriter sw = new StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                //  Create a form to contain the grid
                Table table = new Table();

                //  add the header row to the table
                if (gv.HeaderRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
                    table.Rows.Add(gv.HeaderRow);
                }

                //  add each of the data rows to the table
                foreach (GridViewRow row in gv.Rows)
                {
                    GridViewExportUtil.PrepareControlForExport(row);
                    table.Rows.Add(row);
                }

                //  add the footer row to the table
                if (gv.FooterRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.FooterRow);
                    table.Rows.Add(gv.FooterRow);
                }

                //  render the table into the htmlwriter
                table.RenderControl(htw);

                //  render the htmlwriter into the response
                HttpContext.Current.Response.Write(sw.ToString());
                HttpContext.Current.Response.End();
            }
        }
    }

    /// <summary>
    /// Replace any of the contained controls with literals
    /// </summary>
    /// <param name="control"></param>
    private static void PrepareControlForExport(Control control)
    {
        for (int i = 0; i < control.Controls.Count; i++)
        {
            Control current = control.Controls[i];
            if (current is LinkButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
            }
            else if (current is ImageButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
            }
            else if (current is HyperLink)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
            }
            else if (current is DropDownList)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
            }
            else if (current is CheckBox)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
            }

            if (current.HasControls())
            {
                GridViewExportUtil.PrepareControlForExport(current);
            }
        }
    }
}

Привет, это решение - экспортировать сетку в файл Excel, это может помочь

Gaurav
источник
7
Нет, это генерирует HTML, помеченный как файл Excel, а не как настоящий файл Excel. Да, сам Excel откроет это ОК, но другие программы, использующие электронные таблицы, включая, например, бесплатное средство просмотра Microsoft Excel, не примут его. Вам бы лучше создать настоящий файл Excel, используя одну из библиотек здесь.
Rup
Вам также следует использовать System.Net.Mime.ContentDisposition для генерации текста заголовка размещения содержимого, а не для добавления строки - это будет корректно работать с именами файлов, содержащими пробелы и т. Д.
Rup
12

Вы можете создавать красиво отформатированные файлы Excel, используя эту библиотеку: http://officehelper.codeplex.com/documentation.
См. Пример ниже:

using (ExcelHelper helper = new ExcelHelper(TEMPLATE_FILE_NAME, GENERATED_FILE_NAME))
{
    helper.Direction = ExcelHelper.DirectionType.TOP_TO_DOWN;
    helper.CurrentSheetName = "Sheet1";
    helper.CurrentPosition = new CellRef("C3");

    //the template xlsx should contains the named range "header"; use the command "insert"/"name".
    helper.InsertRange("header");

    //the template xlsx should contains the named range "sample1";
    //inside this range you should have cells with these values:
    //<name> , <value> and <comment>, which will be replaced by the values from the getSample()
    CellRangeTemplate sample1 = helper.CreateCellRangeTemplate("sample1", new List<string> {"name", "value", "comment"}); 
    helper.InsertRange(sample1, getSample());

    //you could use here other named ranges to insert new cells and call InsertRange as many times you want, 
    //it will be copied one after another;
    //even you can change direction or the current cell/sheet before you insert

    //typically you put all your "template ranges" (the names) on the same sheet and then you just delete it
    helper.DeleteSheet("Sheet3");
}        

где образец выглядит так:

private IEnumerable<List<object>> getSample()
{
    var random = new Random();

    for (int loop = 0; loop < 3000; loop++)
    {
        yield return new List<object> {"test", DateTime.Now.AddDays(random.NextDouble()*100 - 50), loop};
    }
}
неизвестно
источник
10

Самый простой и быстрый способ создать файл Excel из C # - использовать инструмент повышения производительности Open XML. Средство повышения производительности Open XML поставляется с установкой Open XML SDK. Инструмент обратный инжиниринг любого файла Excel в код C #. Затем можно использовать код C # для повторной генерации этого файла.

Обзор вовлеченного процесса:

  1. Установите Open XML SDK с помощью инструмента.
  2. Создайте файл Excel, используя последний клиент Excel с желаемым внешним видом. Назови этоDesiredLook.xlsx .
  3. Откройте инструмент DesiredLook.xlsxи нажмите кнопку «Отразить код» вверху. введите описание изображения здесь
  4. Код C # для вашего файла будет сгенерирован на правой панели инструмента. Добавьте это в свое решение C # и создайте файлы с таким желаемым внешним видом.

В качестве бонуса, этот метод работает для любых файлов Word и PowerPoint. Как разработчик C #, вы будете вносить изменения в код в соответствии со своими потребностями.

Я разработал простое приложение WPF на github, которое будет работать на Windows для этой цели. Существует класс-заполнитель, в GeneratedClassкоторый можно вставить сгенерированный код. Если вы вернетесь к одной версии файла, он сгенерирует файл Excel следующим образом:

введите описание изображения здесь

Taterhead
источник
1
Я еще не пробовал это решение Open XML SDK, но я обязательно его проверю. Я работал с такими инструментами много лет и не знал об этом. Я опубликовал свой собственный простой FOSS для преобразования файлов в XLSX с помощью .NET: github.com/TonyGravagno/NebulaXConvert
TonyG