Как я могу создать электронную таблицу Excel с помощью C#, не требуя установки Excel на машине, на которой выполняется код?
Предполагая, что вы пытались сделать что-то без библиотеки или внешнего кода, я не могу говорить о файле xls, но для файлов xlsx почему бы не начать с того, чтобы взять существующий, переименовать его в zip-файл и изучить его содержимое? Немногое реверс-инжиниринга многое вам расскажет. В разных папках и подпапках есть несколько разных XML-файлов и файлов rels. Попробуйте изучить это и посмотреть, можно ли это воспроизвести, или посмотрите, сможете ли вы найти документацию по различным пространствам имен / схемам xml.





На самом деле вы можете захотеть проверить классы взаимодействия, доступные в C# (например, Microsoft.Office.Interop.Excel. Вы говорите, что нет OLE (а это не так), но классы взаимодействия очень просты в использовании. Ознакомьтесь с Документация по C# здесь (Interop for Excel начинается на странице 1072 документа C# PDF).
Вы можете быть впечатлены, если не пробовали их.
Обратите внимание на Microsoft позиция по этому поводу:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
Но вы должны убедиться, что вы все утилизируете вручную, иначе у вас будет утечка памяти.
@Ricky B: Кроме того, по моему опыту взаимодействия, он действительно использует excel. Каждый раз, когда мы его использовали, если Excel не был установлен на машине, мы получали исключения COM.
В случае OLE, даже при очень тщательной утилизации, в конечном итоге происходит утечка памяти или сбои. Это, пожалуй, нормально для обслуживаемых приложений / рабочих станций, но не рекомендуется для серверов (у MS есть база знаний, в которой это указано). Для нашего сервера мы просто перезагружаем его каждую ночь. Опять же, все работает нормально.
@Geoffrey: ах, хорошо, ты собираешься заставить меня работать над этим :) -> support.microsoft.com/kb/257757 Microsoft в настоящее время не рекомендует и не поддерживает автоматизацию приложений Microsoft Office из любых автоматических, неинтерактивных клиентских приложений ...
Я перехожу к этому обсуждению после того, как больше недели боролся с взаимодействием, и, если ваши потребности не очень просты, это не сработает. Поддержка форматирования вашей электронной таблицы ужасна, что, возможно, является причиной создания файла .xls, а не просто плоского файла .csv. Например, пробовали ли вы вывести в ячейке более 911 символов или пытались установить одинаковую ширину объединенных ячеек? У меня есть, и я не могу сказать вам, насколько я ненавижу это дерьмо сейчас ... Сделайте себе одолжение и воспользуйтесь одной из бесплатных библиотек, упомянутых в этом обсуждении.
Я еще не изменил Interop на EPPlus (но уже на полпути), поэтому я действительно не знаю, насколько лучше с ним жизнь, но, имея дело с Interop, я испытывал столько боли в очень неожиданных случаях почти каждый раз, когда мне было нужно что-то более сложное, чем просто создать файл .xls / .xlsx с простой таблицей внутри. И упомянутая выше «магия дважды проверьте, чтобы избавиться от всего» - одна из тех повседневных проблем. Но да, это работает, и в большинстве случаев этого достаточно.
Предупреждение: библиотека Microsoft.Office.Interops зависит от устанавливаемого Excel. Таким образом не отвечает на вопрос пользователя
Он буквально говорит, что не хочет устанавливать офис.
Чрезвычайно легким вариантом может быть использование HTML-таблиц. Просто создайте теги head, body и table в файле и сохраните его как файл с расширением .xls. Есть специальные атрибуты Microsoft, которые можно использовать для стилизации вывода, включая формулы.
Я понимаю, что вы, возможно, не кодируете это в веб-приложении, но вот пример композиции файла Excel через таблицу HTML. Этот метод можно использовать, если вы кодируете консольное приложение, настольное приложение или службу.
Это настолько специальное решение, но оно работает (не говоря уже о выдаче предупреждения об открытии в Excel) и настолько простое, что заслуживает своего решения. Хотя только для того, чтобы показать, что вы можете экспортировать файл excel :))
Это решение сработало для меня, просто обратите внимание, что вы не можете использовать расширение .xlsx
Некоторые люди в моей организации не могут открывать файлы Excel, созданные таким образом в Office 2010 и более поздних версиях. Не знаю, в чем проблема, но мне пришлось свернуть собственную реализацию OpenXML. (см. ответ Соггера)
Вы можете использовать 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();
}
РЕДАКТИРОВАТЬ - Еще несколько ссылок:
Может кто-нибудь подтвердить, работает ли это при работе в x64? Я почти уверен, что Jet работает только в том случае, если ваше приложение скомпилировано или запущено в 32-битном режиме.
Я только что проверил это соединение, и оно не удалось на Windows Server 2008 R2 x64 RC, кажется, что нужно установить драйвер системы Office 2007: Компоненты подключения к данным [microsoft.com/downloads/…
Будьте очень осторожны с этим - это большая уродливая путаница (например, иногда он угадывает тип столбца и отбрасывает все данные, которые не подходят).
При использовании этого метода нужно быть очень осторожным. Я обнаружил, что это очень ненадежно для данных, которые не в идеальном формате.
Как человек, которому приходилось использовать OleDb в большом проекте, я говорю: «Держитесь подальше от него!» Иногда он не может получить значение ячейки только потому, что не может понять формат. У него нет операции удаления. Он работает совершенно иначе и непредсказуемо даже при малейшей смене провайдера. Я бы сказал, выбери проверенное коммерческое решение.
Microsoft обновила Jet, попробуйте эту ссылку stackoverflow.com/questions/14401729/…
В предыдущей работе мы использовали Распространяемый компонент ядра СУБД Microsoft Access 2010. Он принял форму драйвера OLEDB, который позволял читать и записывать файлы Excel, а также файлы формата Access. Обратите внимание, что эта загрузка не требует установки всего пакета Office. Также обратите внимание, что он поставляется как в 32-битном, так и в 64-битном вариантах. Очень важно сопоставить 32-битную или 64-битную версию с архитектура хост-процесса, который будет обращаться к файлу (ам). В нашем случае хост-процессом был SSIS.
Вы можете взглянуть на GemBox.Spreadsheet.
У них есть бесплатная версия со всеми функциями, но с ограничением до 150 строк на лист и 5 листов на книгу, если это соответствует вашим потребностям.
Сам пока не пользовался, но смотрится интересно.
Решение с открытым исходным кодом Java - POI Apache. Возможно, здесь есть способ настроить взаимодействие, но я недостаточно знаю Java, чтобы ответить на этот вопрос.
Когда я исследовал эту проблему, я остановился на сборках Interop.
Вы можете рассмотреть возможность создания файлов в формате Таблица XML 2003. Это простой формат XML с использованием хорошо документированная схема.
Вот способ сделать это с помощью LINQ to XML вместе с образцом кода:
Быстрый импорт и экспорт данных Excel с помощью LINQ to XML
Это немного сложно, поскольку вам нужно импортировать пространства имен и так далее, но это позволяет избежать любых внешних зависимостей.
(Кроме того, конечно, это VB .NET, а не C#, но вы всегда можете изолировать материал VB .NET в своем собственном проекте, чтобы использовать XML-литералы, а все остальное делать на C#.)
Я согласен с созданием таблиц XML, вот пример того, как это сделать для C# 3 (все просто пишут об этом в блогах в VB 9: P) http://www.aaron-powell.com/linq-to-xml-to-excel
Вы когда-нибудь пробовали силк?
Раньше мы генерировали таблицы Excel в классическом формате asp как sylk, а сейчас мы ищем также и Excelgenerater.
Преимущества sylk в том, что вы можете форматировать ячейки.
Различные доступные XML-библиотеки Office 2003 довольно хорошо работают с небольшими файлами Excel. Однако я считаю проблемой сам размер большой книги, сохраненной в формате XML. Например, рабочая книга, с которой я работаю, будет иметь размер 40 МБ в новом (и, по общему признанию, более плотно упакованном) формате XLSX, превратится в файл XML размером 360 МБ.
Насколько я понял, есть два коммерческих пакета, которые позволяют вывод в старые двоичные форматы файлов. Они есть:
Ни то, ни другое не из дешевых (я думаю, 500 и 800 долларов соответственно). но оба работают независимо от самого Excel.
Что мне было бы интересно, так это модуль вывода Excel для подобных OpenOffice.org. Интересно, можно ли их портировать с Java на .Net.
Этот работает как с .net, так и с java, и стоит недорого. SmartXLS smartxls.com
Коммерческое решение SpreadsheetGear для .NET сделает это.
Вы можете увидеть живые образцы ASP.NET (C# и VB) здесь и загрузить ознакомительную версию здесь.
Отказ от ответственности: я владею SpreadsheetGear LLC
У вас отличный продукт, но я думаю, что многие здесь ждут бесплатных решений. Это могло бы объяснить низкие голоса.
Вы можете использовать ExcelXmlWriter.
Работает нормально.
Я недавно использовал FlexCel.NET и обнаружил, что это отличная библиотека! Я не говорю этого о слишком многих программных продуктах. Нет смысла описывать здесь всю коммерческую идею, вы можете прочитать обо всех функциях на их веб-сайте.
Это коммерческий продукт, но вы получите полный исходный код, если купите его. Итак, я полагаю, вы могли бы скомпилировать его в свою сборку, если бы действительно захотели. В противном случае это всего лишь одна дополнительная сборка для xcopy - без настройки, установки или чего-то в этом роде.
Я не думаю, что вы найдете способ сделать это без сторонних библиотек, поскольку .NET framework, очевидно, не имеет встроенной поддержки для этого, а OLE Automation - это просто целый мир боли.
Я использовал несколько вариантов:
Если XLSX необходим: ExcelPackage - хорошее начало, но оно исчезло, когда разработчик прекратил работу над ним. ExML взял оттуда и добавил несколько функций. ExML - неплохой вариант, я все еще использую его на нескольких производственных сайтах.
Однако для всех моих новых проектов я использую NPOI, порт .NET для POI Apache. НПОИ 2.0 (Альфа) также поддерживает XLSX.
Будьте осторожны с ExcelPackage, если вам нужно поддерживать XLS. Мне было трудно с этим, и в конце концов я перешел на ExcelLibrary.
Определенно верно. ExcelPackage / ExML - хороший вариант, только если вам нужна поддержка XLSX.
Обратите внимание, что у ExcelPackage есть преемник: EPPlus (epplus.codeplex.com), который поддерживает XLSX. Единственное, что меня беспокоит, по сравнению, например, с NPOI, - это производительность, например когда много столбцов.
Я успешно использовал следующие проекты с открытым исходным кодом:
ExcelPackage для форматов OOXML (Office 2007)
NPOI для формата .XLS (Office 2003). НПОИ 2.0 (Beta) также поддерживает XLSX.
Взгляните на мои сообщения в блоге:
Создание электронных таблиц Excel .XLS и .XLSX на C#
NPOI с таблицей Excel и динамической диаграммой
Примечание о NPOI - ссылки на строки и столбцы начинаются с нуля. Хорошо работает для заполнения существующего шаблона.
Я тоже голосую за GemBox.Spreadsheet.
Очень быстрый и простой в использовании, с множеством примеров на их сайте.
Взял свои задачи по отчетности на совершенно новый уровень скорости выполнения.
Бесплатная версия ограничена: максимальное количество строк на листе - 150.
Некоторая полезная автоматизация Excel на C#, вы можете найти по следующей ссылке.
http://csharp.net-informations.com/excel/csharp-excel-tutorial.htm
Болтон.
Что ж,
вы также можете использовать стороннюю библиотеку, например Задавать.
Эта библиотека имеет то преимущество, что не требует установки Excel на вашем компьютере, что было бы идеально в вашем случае.
Чтобы быть более точным, вы можете использовать Aspose.Cells для .NET, чтобы создавать файлы Excel (XLS, XLSX) в вашем приложении .NET.
Да, вы можете, если вы не против заплатить минимальный лицензионный сбор в размере 999 долларов. Попробуйте библиотеку MikesKnowledgeBase ... которая на 999 долларов дешевле этой !!
Если вам нравится формат xlsx, попробуйте мой проект GitHub, EPPlus. Все началось с исходников из ExcelPackage, но сегодня это полная переработка. Он поддерживает диапазоны, стили ячеек, диаграммы, формы, изображения, именованные диапазоны, автофильтр и многое другое.
Лицензия теперь LGPL, примечания к выпуску здесь: epplus.codeplex.com/releases/view/79802
Примеры были полезны. Мне удалось сменить код с использованием библиотеки взаимодействия Microsoft (ужасно медленной) на эту библиотеку (версия 4.x) за пару часов. Мой тест записывает файл с двумя вкладками и примерно 750 000 ячеек. Использование взаимодействия с MS заняло 13 минут. Использование EPPlus заняло 10 секунд, что примерно в 80 раз больше. Очень счастлив!
@ JanKällman Вам следует обновить страницу CodePlex, чтобы показать, что у вас есть доступные методы: LoadFromCollection<T>, LoadFromDataTable и т. д. (Можно найти через здесь)
Для ясности в этом треде, LGPL позволяет связывать программное обеспечение без возникновения заразной части GPL. Вам нужно только открыть исходный код изменений, которые вы вносите в ClosedXml, или если вы напрямую помещаете исходный код (в отличие от ссылок на сборки ClosedXml) внутри своего приложения, тогда вам нужно открыть исходный код вашего приложения.
@Paul Chernoch: Мы очень быстро заполняем большие листы Excel с помощью взаимодействия. Секрет в том, чтобы сделать массовое обновление. Создайте блок объекта [,], заполните его, затем запишите эту матрицу в Excel за один раз: excelWorksheet.get_Range (range) .Value2 = block;
Похоже, лицензирование переходит с LGPL на лицензию Polyform Noncommercial 1.0.0.
EPPlus версии 5 не бесплатно?
Вы можете использовать библиотеку под названием ExcelLibrary. Это бесплатная библиотека с открытым исходным кодом, размещенная на Google Code:
Похоже, это порт 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 (LGPL) - больше не поддерживается
EPPlus 5 - Polyform Noncommercial - С мая 2020 г.
NPOI - Лицензия Apache
Вот пример кода для 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, но меня действительно впечатлила вышеуказанная функциональность.
ExcelLibrary был заменен исключительным EPPlus - epplus.codeplex.com. Ян регулярно обновляет его. Мы использовали его, и это один из лучших проектов с открытым исходным кодом, с которыми мы работали.
Следует отметить, что ExcelLibrary имеет множество проблем с производительностью при работе с большими наборами данных (более 5000 строк с большим количеством столбцов). В настоящее время выполняется серьезная модификация базы кода на работе, чтобы мы могли использовать ее в проекте.
EPPlus кажется гораздо менее глючным, чем ExcelLibrary, НО это GPL и, следовательно, только решение для проектов с открытым исходным кодом.
-1 Если вы собираетесь опубликовать образец кода, вы также можете убедиться, что он правильный. Используйте метод Dispose этого интерфейса, чтобы явно освободить неуправляемые ресурсы вместе со сборщиком мусора. Потребитель объекта может вызвать этот метод, когда объект больше не нужен.
EPPlus фактически по-прежнему технически GPL, потому что это производная работа (т. Е. Кодовая база по-прежнему основана на ExcelLibrary, и, поскольку это GPL, то же самое и EPPlus ... вы не можете внести некоторые изменения в код GPL и использовать лицензию LGPL. в теме). Кто-нибудь знает, как писать в Excel, используя коммерческий код или истинный LGPL (или аналогичный лицензионный код).
ExcelLibrary больше не работает. Если вы хотите писать файлы Excel 2003 (.xls), эта библиотека отлично работает: CSharpJExcel sourceforge.net/projects/jexcelapi Убедитесь, что вы загрузили порт C#.
А что насчет ClosedXML? Я могу оказаться полезным в ваших проектах.
Может быть aspose.com/products/cells или gemboxsoftware.com/spreadsheet/overview
Я попробовал ExcelLibrary, все, что он мог сделать, это создать «поврежденный файл», ничего особенного, всего 3 столбца, небольшой файл. Excel 2016 не открывался. Пробовал автоматическое создание файлов ROM DataTable.
EPPlus - это LGPL до версии 5. Если вы используете в своем коде версию 5 или выше, будет создано исключение, если у вас нет лицензионного ключа.
Вы можете просто записать его в XML, используя формат Excel XML, и назвать его с расширением .XLS, и он откроется в excel. Вы можете управлять всем форматированием (полужирным шрифтом, шириной и т. д.) В заголовке XML-файла.
Есть пример XML из Википедии.
Если вы создаете файлы Excel 2007/2010, попробуйте этот проект с открытым исходным кодом: https://github.com/closedxml/closedxml
It provides an object oriented way to manipulate the files (similar to VBA) without dealing with the hassles of XML Documents. It can be used by any .NET language like C# and Visual Basic (VB).
ClosedXML allows you to create Excel 2007/2010 files without the Excel application. The typical example is creating Excel reports on a web server:
var workbook = new XLWorkbook(); var worksheet = workbook.Worksheets.Add("Sample Sheet"); worksheet.Cell("A1").Value = "Hello World!"; workbook.SaveAs("HelloWorld.xlsx");
Я пробовал использовать это в проекте, который строит довольно большие листы Excel. Отличная библиотека, но очень плохая по производительности. Я только что сравнил проект, над которым я работаю: ClosedXML (v 0.53.3) занял 92 489 мс, тогда как EPPlus (v 2.9.03, для тестирования - мы не можем использовать, потому что это GPL) занял 16 500 мс.
@Druid лицензия LGPL при условии, что вы не изменяете исходный код на ClosedXML, можно бесплатно использовать epplus.codeplex.com/license
Вы можете создавать красиво отформатированные файлы 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};
}
}
Устаревший код в codeplex?
http://www.codeproject.com/KB/cs/Excel_and_C_.aspx <= почему бы просто не использовать встроенный Power Windows, просто установить офис на сервере, любое приложение, которое вы устанавливаете, можно автоматизировать.
Намного проще просто использовать собственные методы.
Если он установлен, вы можете использовать его, это самая крутая и малоиспользуемая функция в Windows, она была названа COM еще в старые добрые времена, и это экономит вам массу времени и боли.
Или, что еще проще, просто используйте расходные материалы ref lib MS - http://csharp.net-informations.com/excel/csharp-create-excel.htm
Почему второй способ проще? Разве это не то же самое (добавление библиотеки собственных объектов в ваш проект)? Вам нужно установить Excel, чтобы эта библиотека объектов работала?
Microsoft не рекомендует и не поддерживает автоматизацию Office из неинтерактивных приложений, таких как ASP.NET. См. support.microsoft.com/kb/257757
Когда дело доходит до автоматизации, Excel работает ненадежно и медленно.
Некоторые сторонние поставщики компонентов, такие как Infragistics или Syncfusion, предоставляют очень хорошие возможности экспорта в Excel, которые не требуют установки Microsoft Excel.
Поскольку эти поставщики также предоставляют расширенные компоненты сетки пользовательского интерфейса, эти компоненты особенно удобны, если вы хотите, чтобы стиль и макет экспорта в Excel имитировали текущее состояние сетки в пользовательском интерфейсе вашего приложения.
Если ваш экспорт предназначен для выполнения на стороне сервера с акцентом на экспортируемые данные и без ссылки на пользовательский интерфейс, я бы выбрал один из бесплатных вариантов с открытым исходным кодом (например, ExcelLibrary).
Раньше я участвовал в проектах, в которых пытались использовать автоматизацию на стороне сервера в пакете Microsoft Office. Основываясь на этом опыте, я настоятельно рекомендую не использовать такой подход.
Посмотрите примеры создания файлов Excel.
Примеры есть в C# и VB.NET
Он управляет файлами XLS XLSX и CSV Excel.
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, это может вам помочь
Нет, это генерирует HTML, помеченный как файл Excel, а не как настоящий файл Excel. Да, сам Excel откроет это нормально, но другие программы, использующие электронные таблицы, в том числе, например, бесплатное средство просмотра Excel от Microsoft, не примут его. Лучше создать настоящий файл Excel, используя одну из библиотек здесь.
Вы также должны использовать System.Net.Mime.ContentDisposition для генерации текста заголовка Content-Disposition, а не добавления строки - это правильно справится с именами файлов, которые содержат пробелы и т. д.
GridViewExportUtil только для Интернета. А для Windows Forms, WPF, консоли, служебной Windows, модульного теста или надстройки?
А как насчет использования Open XML SDK 2.0 для Microsoft Office?
Несколько преимуществ:
Ссылки:
Важно отметить, что размер DLL для этого составляет чуть более 5 МБ и ограничен форматами Office 2007. Но, безусловно, самое простое и быстрое решение, которое мне подходит.
Просто предупреждаю, что v2.5 отсутствует и может быть загружена здесь.
SDK моделирует XML в классы, так что каждый тег XML сопоставляется с тегом, а затем вам необходимо правильно построить иерархию классов (каждый экземпляр имеет набор дочерних экземпляров / тегов). Это означает, что вы должны знать XML-структуру файла Excel, что очень сложно. Намного проще использовать упомянутую выше оболочку, такую как EPPlus, которая упрощает работу.
Отличный образец Microsoft Open XML SDK - Open XML Writer можно найти по адресу polymathprogrammer.com/2012/08/06/… Или см. Решение для переполнения стека stackoverflow.com/questions/11370672/…
Я считаю, что средство записи Open XML из пакета Microsoft Open XML SDK великолепно. Используя приведенные выше решения (особенно образец Винсента Тома (Poly Math)), легко создать писатель, который обрабатывает большие наборы данных и записывает записи способом, аналогичным и не слишком сложным для того, что вы бы сделали для CSV; но вместо этого вы пишете xml. Open XML - это образ мышления, в котором Microsoft считает свои новые форматы Office. И вы всегда можете переименовать их из .xslx в .zip-файлы, если вам захочется потрогать их XML-содержимое.
Обратите внимание, что Open XML SDK теперь имеет открытый исходный код и размещен на github. Также вам не нужно устанавливать SDK, просто запустите nuget и DocumentFormat.OpenXml - это все, что вам нужно. Он работает со стандартом .net 1.3.
Как это было интересно, и ваш ответ заставил меня это усвоить. Я только начал заниматься программированием и мне интересен такой контент.
Не забудьте загрузить Инструмент повышения производительности OpenXML с сайта Microsoft при использовании этого API. Как я работаю: создайте документ с нужным мне содержанием и форматом в Excel и сохраните его. Откройте его с помощью инструмента. Очистите интересующий меня код от кода, отраженного в инструменте, и начните с него. Я также использую этот инструмент для проверки и проверки своих результатов на ошибки. Когда я хочу добавить новую функцию в свой код, я использую функцию инструментов «Diff», чтобы выяснить, как эта функция должна быть закодирована. Это действительно важный инструмент разработки OpenXML
Просто хочу добавить еще одну ссылку на стороннее решение, которое напрямую решает вашу проблему: http://www.officewriter.com
(Отказ от ответственности: я работаю в SoftArtisans, компании, которая делает OfficeWriter)
Вот полностью бесплатная библиотека C#, которая позволяет экспортировать из DataSet, DataTable или List<> в настоящий файл Excel 2007 .xlsx, используя библиотеки OpenXML:
http://mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
Предоставляется полный исходный код - бесплатно - вместе с инструкциями и демонстрационным приложением.
После добавления этого класса в приложение вы можете экспортировать DataSet в Excel всего одной строкой кода:
CreateExcelFile.CreateExcelDocument(myDataSet, "C:\Sample.xlsx");
Нет ничего проще ...
И для этого даже не требуется наличие Excel на вашем сервере.
Это кажется немного вводящим в заблуждение, поскольку вы просите пожертвование, чтобы получить все функции.
Отчасти это правда: полностью бесплатная версия создаст для вас идеальный файл .xlsx, и весь исходный код предоставлен. Если вы пожертвуете 10 долларов или более одной из этих двух благотворительных организаций (от которых я не получаю абсолютно ничего), то вы получите «лучшую» версию, показывающую, как выполнять форматирование, даты и т. д. Учитывая стоимость сторонних продуктов, я полагаю Вместо этого пожертвование 10 долларов на доброе дело того стоит!
Я использую следующий код для создания файла excel 2007, который создает файл и записывает в этот файл, но когда я открываю файл, он дает мне ошибку, которая exel не может открыть файл. Возможно, файл bcz поврежден или расширение файла несовместимо. но если я использовал .xls для файла, он работал штраф
for (int i = 0; i < TotalFile; i++)
{
Contact.Clear();
if (innerloop == SplitSize)
{
for (int j = 0; j < SplitSize; j++)
{
string strContact = DSt.Tables[0].Rows[i * SplitSize + j][0].ToString();
Contact.Add(strContact);
}
string strExcel = strFileName + "_" + i.ToString() + ".xlsx";
File.WriteAllLines(strExcel, Contact.ToArray());
}
}
также ссылка
http://dotnet-magic.blogspot.in/2011/10/createformat-excel-file-from-cnet.html
Все это зависит от вашего класса Contact, и вы не сказали нам, что это такое. Если это работает для xls, скорее всего, вы на самом деле пишете HTML, который не является настоящим файлом Excel. И ваша ссылка использует взаимодействие, которое как указано выше не должно использоваться на стороне сервера и может медленно заполнять большие таблицы.
Контакт - это связанный список, а не класс. Объявить связанный список и использовать его, потому что я не знаю размера данных, поэтому я использовал связанный список.
О, так вы создаете простой текстовый файл с одним элементом в строке? Значит, Excel рассматривает его как CSV без запятых?
Я написал простой код для экспорта набора данных в 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();
}
Однако, как говорится в статье, это XML, который Excel будет читать, а не на самом деле файл XLS, что означает, что он может работать только в Excel, а не в других программах, которые читают электронные таблицы. Но это, вероятно, лучше, чем ответы в эквивалентной таблице HTML здесь!
Поддерживает xlsx? OpenXML?
Типа это Open XML, но вы можете писать только файл .xls и отлично работает. Позаботьтесь о пустых местах в тегах. Используйте мой код, отредактированный ниже.
OpenXML также является хорошей альтернативой, которая помогает избежать установки MS Excel на сервере. Open XML SDK 2.0, предоставляемый Microsoft, упрощает задачу управления пакетами Open XML и базовыми элементами схемы Open XML внутри пакета. Интерфейс прикладного программирования (API) Open XML инкапсулирует множество общих задач, которые разработчики выполняют с пакетами Open XML.
Проверьте это OpenXML: альтернатива, которая помогает избежать установки MS Excel на сервере
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.
Syncfusion Не бесплатно
Самый простой и быстрый способ создать файл Excel из C# - использовать инструмент повышения производительности Open XML. Инструмент повышения производительности Open XML поставляется с установкой Open XML SDK. Инструмент выполняет обратное преобразование любого файла Excel в код C#. Затем код C# можно использовать для повторного создания этого файла.
Обзор вовлеченного процесса:
DesiredLook.xlsx.DesiredLook.xlsx и нажмите кнопку Reflect Code вверху.

В качестве бонуса этот метод работает с любыми файлами Word и PowerPoint. Как разработчик C#, вы затем внесете в код изменения в соответствии со своими потребностями.
Я разработал простое приложение WPF на github, который будет работать в Windows для этой цели. Существует класс-заполнитель GeneratedClass, куда вы можете вставить сгенерированный код. Если вы вернетесь к одной версии файла, он сгенерирует файл Excel, подобный этому:
Я еще не пробовал это решение Open XML SDK, но вау, я обязательно его проверю. Я работал с подобными инструментами много лет и не знал об этом. Я опубликовал свой собственный простой FOSS для преобразования файлов в XLSX с помощью .NET: github.com/TonyGravagno/NebulaXConvert
Если вы создаете таблицу данных или datagridview из кода, вы можете сохранить все данные, используя этот простой метод. Этот метод не рекомендуется, но он работает на 100%, даже если вы не устанавливаете MS Excel на свой компьютер.
try
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel Documents (*.xls)|*.xls";
saveFileDialog1.FileName = "Employee Details.xls";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
string fname = saveFileDialog1.FileName;
StreamWriter wr = new StreamWriter(fname);
for (int i = 0; i <DataTable.Columns.Count; i++)
{
wr.Write(DataTable.Columns[i].ToString().ToUpper() + "\t");
}
wr.WriteLine();
//write rows to excel file
for (int i = 0; i < (DataTable.Rows.Count); i++)
{
for (int j = 0; j < DataTable.Columns.Count; j++)
{
if (DataTable.Rows[i][j] != null)
{
wr.Write(Convert.ToString(getallData.Rows[i][j]) + "\t");
}
else
{
wr.Write("\t");
}
}
//go to next line
wr.WriteLine();
}
//close file
wr.Close();
}
}
catch (Exception)
{
MessageBox.Show("Error Create Excel Sheet!");
}
Некоторое время назад я создал DLL поверх NPOI. Пользоваться им очень просто:
IList<DummyPerson> dummyPeople = new List<DummyPerson>();
//Add data to dummyPeople...
IExportEngine engine = new ExcelExportEngine();
engine.AddData(dummyPeople);
MemoryStream memory = engine.Export();
Вы можете прочитать об этом на здесь.
Кстати, это 100% открытый исходный код. Не стесняйтесь использовать, редактировать и делиться;)
Один действительно простой вариант, о котором часто забывают, - это создать отчет .rdlc с использованием Отчетность Microsoft и экспортировать его в формат Excel. Вы можете создать его в Visual Studio и сгенерировать файл, используя:
localReport.Render("EXCELOPENXML", null, ((name, ext, encoding, mimeType, willSeek) => stream = new FileStream(name, FileMode.CreateNew)), out warnings);
Вы также можете экспортировать его в .doc или .pdf, используя "WORDOPENXML" и "PDF" соответственно, и он поддерживается на многих различных платформах, таких как ASP.NET и SSRS.
Намного проще вносить изменения в визуальный дизайнер, где вы можете видеть результаты, и поверьте мне, как только вы начнете группировать данные, форматировать заголовки групп, добавлять новые разделы, вы не захотите возиться с десятками узлов XML.
полный образец исходного кода? rdlc выдает память в ASP.NET travis.io/blog/2014/10/27/rdlc-performance-issues-dotnet45 и stackoverflow.com/questions/33436607/…
Чтобы сохранить xls в формате xlsx, нам просто нужно вызвать метод SaveAs из библиотеки Microsoft.Office.Interop.Excel. Этот метод принимает около 16 параметров, и один из них также является форматом файла.
Документ Microsoft: Здесь Аргументы метода SaveAs
Объект, который нам нужно передать, похож на
wb.SaveAs(filename, 51, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, false, false, 1,1, true,
System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value)
Здесь 51 - это значение перечисления для XLSX.
Для SaveAs в различных форматах файлов вы можете обратиться к xlFileFormat
Также есть старый ответ об использовании Office Interop.
проверьте это, нет необходимости в сторонних библиотеках, вы можете просто экспортировать данные с данными в файл Excel, используя это
var dt = "your code for getting data into datatable";
Response.ClearContent();
Response.AddHeader("content-disposition", string.Format("attachment;filename = {0}.xls", DateTime.Now.ToString("yyyy-MM-dd")));
Response.ContentType = "application/vnd.ms-excel";
string tab = "";
foreach (DataColumn dataColumn in dt.Columns)
{
Response.Write(tab + dataColumn.ColumnName);
tab = "\t";
}
Response.Write("\n");
int i;
foreach (DataRow dataRow in dt.Rows)
{
tab = "";
for (i = 0; i < dt.Columns.Count; i++)
{
Response.Write(tab + dataRow[i].ToString());
tab = "\t";
}
Response.Write("\n");
}
Response.End();
Это создает файл с разделением табуляцией и сохраняет его с расширением .XLS, чтобы его открывал Excel. Это не настоящий файл Excel, и вы не можете включать форматирование и т. д. Здесь есть похожие ответы, в которых используется тот же трюк с HTML и неправильным расширением.
Microsoft Graph API предоставляет API файлов и Excel для создания и изменения файлов Excel, хранящихся в OneDrive, как для корпоративных, так и для пользовательских учетных записей. Пакет NuGet Microsoft.Graph предоставляет множество интерфейсов для работы с API файлов и Excel.
{
Name = "myExcelFile.xslx",
File = new Microsoft.Graph.File()
};
// Create an empty file in the user's OneDrive.
var excelWorkbookDriveItem = await graphClient.Me.Drive.Root.Children.Request().AddAsync(excelWorkbook);
// Add the contents of a template Excel file.
DriveItem excelDriveItem;
using (Stream ms = ResourceHelper.GetResourceAsStream(ResourceHelper.ExcelTestResource))
{
//Upload content to the file. ExcelTestResource is an empty template Excel file.
//https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/item_uploadcontent
excelDriveItem = await graphClient.Me.Drive.Items[excelWorkbookDriveItem.Id].Content.Request().PutAsync<DriveItem>(ms);
}
На этом этапе у вас есть файл Excel, созданный в OneDrive пользователя (предприятия или потребителя) или группы. Теперь вы можете использовать от API Excel до вносить изменения в файл Excel без использования Excel и без понимания формата Excel XML.
полный образец? что такое graphClient? ResourceHelper? ExcelTestResource - это пустой файл Excel шаблона?
@Kiquenet graphClient находится в пакете NuGet Microsoft.Graph. Да, ExcelTestResource - это пустой файл Excel. ResourceHelper получает пустой поток файла Excel. Вот пример, в котором используется GraphServiceClient (в этом примере graphClient): github.com/microsoftgraph/dotnetcore-console-sample. В нем нет примера использования API Excel.
Вы можете попробовать мою библиотеку SwiftExcel. Эта библиотека записывает непосредственно в файл, поэтому она очень эффективна. Например, вы можете записать 100 тыс. Строк за несколько секунд без использования памяти.
Вот простой пример использования:
using (var ew = new ExcelWriter("C:\temp\test.xlsx"))
{
for (var row = 1; row <= 10; row++)
{
for (var col = 1; col <= 5; col++)
{
ew.Write($"row:{row}-col:{col}", col, row);
}
}
}
Вы можете установить пакет OpenXml nuget в Visual Studio. Вот небольшой код для экспорта таблицы данных в файл Excel:
Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Spreadsheet
Public Class ExportExcelClass
Public Sub New()
End Sub
Public Sub ExportDataTable(ByVal table As DataTable, ByVal exportFile As String)
' Create a spreadsheet document by supplying the filepath.
' By default, AutoSave = true, Editable = true, and Type = xlsx.
Dim spreadsheetDocument As SpreadsheetDocument = spreadsheetDocument.Create(exportFile, SpreadsheetDocumentType.Workbook)
' Add a WorkbookPart to the document.
Dim workbook As WorkbookPart = spreadsheetDocument.AddWorkbookPart
workbook.Workbook = New Workbook
' Add a WorksheetPart to the WorkbookPart.
Dim Worksheet As WorksheetPart = workbook.AddNewPart(Of WorksheetPart)()
Worksheet.Worksheet = New Worksheet(New SheetData())
' Add Sheets to the Workbook.
Dim sheets As Sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild(Of Sheets)(New Sheets())
Dim data As SheetData = Worksheet.Worksheet.GetFirstChild(Of SheetData)()
Dim Header As Row = New Row()
Header.RowIndex = CType(1, UInt32)
For Each column As DataColumn In table.Columns
Dim headerCell As Cell = createTextCell(table.Columns.IndexOf(column) + 1, 1, column.ColumnName)
Header.AppendChild(headerCell)
Next
data.AppendChild(Header)
Dim contentRow As DataRow
For i As Integer = 0 To table.Rows.Count - 1
contentRow = table.Rows(i)
data.AppendChild(createContentRow(contentRow, i + 2))
Next
End Sub
Private Function createTextCell(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal cellValue As Object) As Cell
Dim cell As Cell = New Cell()
cell.DataType = CellValues.InlineString
cell.CellReference = getColumnName(columnIndex) + rowIndex.ToString
Dim inlineString As InlineString = New InlineString()
Dim t As Text = New Text()
t.Text = cellValue.ToString()
inlineString.AppendChild(t)
cell.AppendChild(inlineString)
Return cell
End Function
Private Function createContentRow(ByVal dataRow As DataRow, ByVal rowIndex As Integer) As Row
Dim row As Row = New Row With {
.rowIndex = CType(rowIndex, UInt32)
}
For i As Integer = 0 To dataRow.Table.Columns.Count - 1
Dim dataCell As Cell = createTextCell(i + 1, rowIndex, dataRow(i))
row.AppendChild(dataCell)
Next
Return row
End Function
Private Function getColumnName(ByVal columnIndex As Integer) As String
Dim dividend As Integer = columnIndex
Dim columnName As String = String.Empty
Dim modifier As Integer
While dividend > 0
modifier = (dividend - 1) Mod 26
columnName = Convert.ToChar(65 + modifier).ToString() & columnName
dividend = CInt(((dividend - modifier) / 26))
End While
Return columnName
End Function
End Class
spreadsheetDocument.Create будет SpreadsheetDocument.Create?
Интересно, почему никто не предложил PowerShell с бесплатным модулем ImportExcel; он с легкостью создает файлы XML-Excel (xlsx).
Особенно просто при создании таблиц Excel из баз данных, таких как SQL Server ...
К вашему сведению, расширение XLSX не имеет ничего общего с XML. Это просто современная (Office 2007+) версия расширения файла XLS.
@TylerH Но они основаны на XML. Файлы XLSX представляют собой файлы .zip XML, аналогичные форматам файлов OpenOffice.
@Rup Да, файлы представляют собой проприетарную оболочку XML-данных. Но это не значит, что файлы являются файлами «XML-Excel». Это просто файлы Excel.
Я снова перекодировал код, и теперь вы можете создать файл .xls, позже вы можете преобразовать его в формат Open XML Excel 2003.
private static void exportToExcel(DataSet source, string fileName)
{
// Documentacion en:
// https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
// https://answers.microsoft.com/en-us/msoffice/forum/all/how-to-save-office-ms-xml-as-xlsx-file/4a77dae5-6855-457d-8359-e7b537beb1db
// https://riptutorial.com/es/openxml
const string startExcelXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+
"<?mso-application progid=\"Excel.Sheet\"?>\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 " +
"xmlns:html=\"http://www.w3.org/TR/REC-html40\">\r\n " +
"xmlns:html=\"https://www.w3.org/TR/html401/\">\r\n " +
"<DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n " +
" <Version>16.00</Version>\r\n " +
"</DocumentProperties>\r\n " +
" <OfficeDocumentSettings xmlns=\"urn:schemas-microsoft-com:office:office\">\r\n " +
" <AllowPNG/>\r\n " +
" </OfficeDocumentSettings>\r\n " +
" <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n " +
" <WindowHeight>9750</WindowHeight>\r\n " +
" <WindowWidth>24000</WindowWidth>\r\n " +
" <WindowTopX>0</WindowTopX>\r\n " +
" <WindowTopY>0</WindowTopY>\r\n " +
" <RefModeR1C1/>\r\n " +
" <ProtectStructure>False</ProtectStructure>\r\n " +
" <ProtectWindows>False</ProtectWindows>\r\n " +
" </ExcelWorkbook>\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=\"dd/mm/yyyy;@\"/>\r\n </Style>\r\n " +
"</Styles>\r\n ";
System.IO.StreamWriter excelDoc = null;
excelDoc = new System.IO.StreamWriter(fileName,false);
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 == 1048576)
{
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++;
}
const string endExcelOptions1 = "\r\n<WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\r\n" +
"<Selected/>\r\n" +
"<ProtectObjects>False</ProtectObjects>\r\n" +
"<ProtectScenarios>False</ProtectScenarios>\r\n" +
"</WorksheetOptions>\r\n";
excelDoc.Write(endExcelOptions1);
excelDoc.Write("</Workbook>");
excelDoc.Close();
}
@Mike Фрагмент "без установки Excel" не имеет ничего общего с профессионализмом. Это о зависимостях. Исходный текст вопроса был сформулирован так: «В идеале мне нужен открытый исходный код, поэтому мне не нужно добавлять какие-либо сторонние зависимости в свой код, и я бы не хотел напрямую использовать Excel для создания файла (с помощью OLE Automation)». К сожалению, вопрос был значительно упрощен.