Время на прочтение
7 мин
Количество просмотров 69K
В современном мире разработки приложений нередко встает необходимость работы с Excel документами. Чаще всего это разного рода отчеты, но иногда xls/x файлы используются в качестве хранилища данных. Например, если пользователь должен иметь возможность загрузить данные в приложение или выгрузить, в человеко-читаемом виде, Excel де-факто является стандартом. Относительно дружелюбный интерфейс, прозрачная структура, в купе с его распространенностью… трудно навскидку назвать решение лучше.
Однако, у многих Excel до сих пор ассоциируется с чем-то тяжелым, неповоротливым и сложным. Давайте посмотрим, как мы — обычные C# разработчики, можем легко сформировать простой Excel документ, на примере табличного отчета.
Историческая справка
Времена, когда доминировал проприетарный формат .xls(Excel Binary File Format) давно прошли и сейчас мы имеем только .xlsx(Excel Workbook), в рамках Office Open XML. Последний представляет собой обычный .zip архив с XML файлами. Не будем углубляться в его структуру, я искренне надеюсь что вам это никогда не понадобится.
На github, и не только, можно найти ряд библиотек, бесплатных и не только. Пожалуй самой популярной является EPPlus. До определенной степени, она довольно хорошо отражает концепцию Excel, именно по этому я всегда использую EPPlus. Версия 4 полностью бесплатна, начиная с 5‐й версии вам потребуется приобрести лицензию для коммерческого использования.
Задача
Итак, предположим, продукт-мэнеджеру ударила в голову идея того, что возможность выгружать некий отчет в формате Excel увеличит кол-во пользователей на 100500%. Проджет-менеджер решает выкатить эту киллер-фичу как хотфикс прямо сегодня — ведь работы всего на пару часов.
Сам по себе, отчет содержит краткое описание компании и историю изменения некоторых экономических показателей. Для простоты все свойства компании — строки. Экономические показатели — большие целые числа и числа с плавающей точкой, а также даты. Предположим, что где-то в недрах микросервисного backend-да есть сервис-генератор подобных отчетов, например по id компании. Однако, поскольку id нет смысла выводить пользователю, идентификатор отсутствует в самой модели отчета.
Аналитик, в свою очередь, выдает задачу с феноменально точным описанием — «Сгенерировать excel отчет на базе данных MarketReport». Что ж, для нашего примера, создадим заглушку — генератор фейковых данных:
Первый запуск
Подключим EPPlus версии 4.5.3.3 и создадим базовую обвязку для будущего генератора.
Сердцем генератора будет метод Generate. ExcelPackage это модель документа, через которую мы и будем осуществлять все взаимодействия с ним. Также имеется конструктор для передачи пути к файлу или потока.
В методе main создается генератор отчетов, а также генератор Excel файлов. Далее полученный файл просто записывается на диск.
При попытке запустить приложение, получаем exception:InvalidOperationException: The workbook must contain at least one worksheet
Все правильно, Excel документ не может существовать без страниц, должна быть хотя бы одна. Добавляем ее, все интуитивно понятно:
var sheet = package.Workbook.Worksheets
.Add("Market Report");
Запускаем снова и… вот оно! Теперь наше приложение генерирует документ и, хотя там еще ничего нет, он уже весит 2,5KB — значит мы работаем с Excel правильно и все идет как надо.
Вывод данных
Давайте выведем основную информацию по компании в шапку. Для доступа к конкретной ячейки объект Cells на странице пакета снабжен удобным индексатором. При этом, до конкретной ячейки можно достучаться как через номер строки и столбца, так и по привычному всем буквенно-числовому коду:
sheet.Cells["B2"].Value = "Company:";
sheet.Cells[2, 3].Value = report.Company.Name;
Полный код вывода шапки.
sheet.Cells["B2"].Value = "Company:";
sheet.Cells[2, 3].Value = report.Company.Name;
sheet.Cells["B3"].Value = "Location:";
sheet.Cells["C3"].Value = $"{report.Company.Address}, " +
$"{report.Company.City}, " +
$"{report.Company.Country}";
sheet.Cells["B4"].Value = "Sector:";
sheet.Cells["C4"].Value = report.Company.Sector;
sheet.Cells["B5"].Value = report.Company.Description;
Для вывода исторических данных понадобится как минимум шапка таблицы и цикл по массиву History:
sheet.Cells[8, 2, 8, 4].LoadFromArrays(new object[][]{ new []{"Capitalization", "SharePrice", "Date"} });
var row = 9;
var column = 2;
foreach (var item in report.History)
{
sheet.Cells[row, column].Value = item.Capitalization;
sheet.Cells[row, column + 1].Value = item.SharePrice;
sheet.Cells[row, column + 2].Value = item.Date;
row++;
}
Предлагаю обратить внимание на метод LoadFromArrays, который заполняет диапазон ячеек рваным(зубчатым) массивом. Здесь мы можем видеть, что типизация теряется и передавая массив object мы ожидаем что EPPlus в конечном итоге использует ToString, чтобы записать переданное в ячейки.
Стилизация
Если вы прямо сейчас откроете документ, то вы возможно увидите не то, что хотелось бы отдать в продакшн в пятницу вечером.
Как это выглядит
Во-первых, шапка никак не выделяется, во-вторых таблица не имеет границ… выравнивание пляшет, даты отображаются магическими числами, а капитализация «уходит в какую-то математику» — как это прокомментировал аналитик.
Да, на все эти красивости у нас уйдет больше года кода, чем на сам вывод данных, и, в конечном тоге, получившаяся каша из логики вывода данных и разметки заставит некоторых усомниться в их компетентности… но, мы же backend разработчики, так давайте сверстаем Excel Sheet!
Размер ячеек
Из коробки у нас есть возможность сделать автофит а так же вручную выставить ширину в соответствии с нашей ситуацией. А ситуация у нас не самая хорошая — по задумке аналитика в шапке у ячеек должен быть автофит, а у ячеек таблицы — тоже автофит. Так в чем же подвох?
Если вы когда-нибудь до этого открывали Excel, то возможно знаете, что ширина ячеек не может отличаться в рамках столбца и автофит будет по самому широкому контенту ячейки. Однако, простые вещи бывает нетак то просто объяснить… Но если вы справитесь, то вот как это будет выглядеть в коде:
sheet.Cells[1, 1, row, column + 2].AutoFitColumns();
sheet.Column(2).Width = 14;
sheet.Column(3).Width = 12;
Формат данных
Как и большая часть стиля ячейки, он задается через одноименное свойство Style. Обратите внимание на вычисление 3-го аргумента индексатора. Это звоночек некачественного кода, но к этому мы вернемся в позже…
sheet.Cells[9, 4, 9 + report.History.Length, 4].Style.Numberformat.Format = "yyyy";
sheet.Cells[9, 2, 9 + report.History.Length, 2].Style.Numberformat.Format = "### ### ### ##0";
Выравнивание
Его можно задать как на ячейке, так и на диапазоне. На самом деле, для EPPlus, это одна и та же сущность — некий ExcelRange, описывающий диапазон ячеек, в том числе и со всего 1 ячейкой.
sheet.Column(2).Style.HorizontalAlignment = ExcelHorizontalAlignment.Left;
sheet.Cells[8, 3, 8 + report.History.Length, 3].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
Стиль текста
Также легко задается, используя Style.Font, кстати, здесь, на 2-й строчке, мы впервые указываем диапазон так, как привыкли его видеть пользователи Excel:
sheet.Cells[8, 2, 8, 4].Style.Font.Bold = true;
sheet.Cells["B2:C4"].Style.Font.Bold = true;
Границы
Задаем стиль линии, а также ее толщину. К этому моменту от кол-ва магических чисел-параметров индексатора уже рябит в глазах, но мы уже на финишной прямой… не так ли?
sheet.Cells[8, 2, 8 + report.History.Length, 4].Style.Border.BorderAround(ExcelBorderStyle.Double);
sheet.Cells[8, 2, 8, 4].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
График
«Ну что за отчет без графиков, верно, Карл?» — ловко подметит специалист по тестированию, и не важно, что этого не было в ТЗ а на часах уже половина 9-го…
Хотя график как сущность сам по себе сложнее таблиц и с графиками мы не работаем каждый день, EPPlus предоставляет довольно понятный API. Давайте добавим простейший график, отражающий рост капитализации:
var capitalizationChart = sheet.Drawings.AddChart("FindingsChart", OfficeOpenXml.Drawing.Chart.eChartType.Line);
capitalizationChart.Title.Text = "Capitalization";
capitalizationChart.SetPosition(7, 0, 5, 0);
capitalizationChart.SetSize(800, 400);
var capitalizationData = (ExcelChartSerie)(capitalizationChart.Series.Add(sheet.Cells["B9:B28"], sheet.Cells["D9:D28"]));
capitalizationData.Header = report.Company.Currency;
Еще, может понадобиться защитить страницу от редактирования:
sheet.Protection.IsProtected = true;
На этом все, репозиторий с рабочим приложением находится здесь.
Заключение
О чем говорит финальная версия метода Generate?
public byte[] Generate(MarketReport report)
{
var package = new ExcelPackage();
var sheet = package.Workbook.Worksheets
.Add("Market Report");
sheet.Cells["B2"].Value = "Company:";
sheet.Cells[2, 3].Value = report.Company.Name;
sheet.Cells["B3"].Value = "Location:";
sheet.Cells["C3"].Value = $"{report.Company.Address}, " +
$"{report.Company.City}, " +
$"{report.Company.Country}";
sheet.Cells["B4"].Value = "Sector:";
sheet.Cells["C4"].Value = report.Company.Sector;
sheet.Cells["B5"].Value = report.Company.Description;
sheet.Cells[8, 2, 8, 4].LoadFromArrays(new object[][]{ new []{"Capitalization", "SharePrice", "Date"} });
var row = 9;
var column = 2;
foreach (var item in report.History)
{
sheet.Cells[row, column].Value = item.Capitalization;
sheet.Cells[row, column + 1].Value = item.SharePrice;
sheet.Cells[row, column + 2].Value = item.Date;
row++;
}
sheet.Cells[1, 1, row, column + 2].AutoFitColumns();
sheet.Column(2).Width = 14;
sheet.Column(3).Width = 12;
sheet.Cells[9, 4, 9+ report.History.Length, 4].Style.Numberformat.Format = "yyyy";
sheet.Cells[9, 2, 9+ report.History.Length, 2].Style.Numberformat.Format = "### ### ### ##0";
sheet.Column(2).Style.HorizontalAlignment = ExcelHorizontalAlignment.Left;
sheet.Cells[8, 3, 8 + report.History.Length, 3].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
sheet.Column(4).Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
sheet.Cells[8, 2, 8, 4].Style.Font.Bold = true;
sheet.Cells["B2:C4"].Style.Font.Bold = true;
sheet.Cells[8, 2, 8 + report.History.Length, 4].Style.Border.BorderAround(ExcelBorderStyle.Double);
sheet.Cells[8, 2, 8, 4].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
var capitalizationChart = sheet.Drawings.AddChart("FindingsChart", OfficeOpenXml.Drawing.Chart.eChartType.Line);
capitalizationChart.Title.Text = "Capitalization";
capitalizationChart.SetPosition(7, 0, 5, 0);
capitalizationChart.SetSize(800, 400);
var capitalizationData = (ExcelChartSerie)(capitalizationChart.Series.Add(sheet.Cells["B9:B28"], sheet.Cells["D9:D28"]));
capitalizationData.Header = report.Company.Currency;
sheet.Protection.IsProtected = true;
return package.GetAsByteArray();
}
Во-первых, прежде всего, о том, что мы успешно справились с задачей, а именно, сгенерировали свой первый Excel отчет, поработали со стилями и даже решили пару попутных проблем.
Во-вторых, возможно имеет смысл искать новою работу, но, забегая вперед, я бы с этим не спешил… Если данная публикация наберет 1+ просмотров, то во второй части мы поговорим о том, как можно отделить стилизацию от логики заполнения данными, упростить манипуляции над ячейками и в целом сделаем код боле поддерживаемым.
Overview
Creating report files in Excel format is a feature that many users need out of their software applications.
In this article, we’ll cover creating an Excel spreadsheet in C# using a third-party library called EPPlus.
EPPlus is a .NET library that reads and writes Excel files using the Open Office XML format (*.xlsx). It is licensed under GNU Library General Public License (LGPL) so it can be freely used in commercial software.
Installation
In Visual Studio 2017, go to Tools -> NuGet Package Manager -> Package Manager Console
In the console window that appears, type the following at the prompt to install it into the current project:
PM > Install-Package EPPlus
After it is finished, check the References under Solution Explorer and verify that the EPPlus assembly is listed.
Add to Project
We add line 7 below so we can use the types inside the namespace:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OfficeOpenXml;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
}
}
}
Create a Workbook
We call the ExcelPackage class constructor to create a workbook. In the below code, we do this within a using block so we don’t have to explicitly dispose of the object.
We add 3 blank worksheets to the workbook by using the Add() method in the Worksheets class. Finally, we save the file to a path using the SaveAs() method.
using (ExcelPackage excel = new ExcelPackage())
{
excel.Workbook.Worksheets.Add("Worksheet1");
excel.Workbook.Worksheets.Add("Worksheet2");
excel.Workbook.Worksheets.Add("Worksheet3");
FileInfo excelFile = new FileInfo(@"C:UsersamirDesktoptest.xlsx");
excel.SaveAs(excelFile);
}
The SaveAs method will throw an exception if there are no worksheets defined.
Select a Worksheet
Let’s say we want to add some data to Worksheet1. How can we target it?
var excelWorksheet = excel.Workbook.Worksheets["Worksheet1"];
Add a Row
Spreadsheets typically have header rows. Let’s add a header row to Worksheet1.
For this, we create a List containing an array of strings:
List<string[]> headerRow = new List<string[]>()
{
new string[] { "ID", "First Name", "Last Name", "DOB" }
};
Before we can pass this object into our worksheet, we must figure out the cell range for the header row:
// Determine the header range (e.g. A1:E1)
string headerRange = "A1:" + Char.ConvertFromUtf32(headerRow[0].Length + 64) + "1";
Here’s how we load the data into the worksheet:
// Popular header row data
excelWorksheet.Cells[headerRange].LoadFromArrays(headerRow);
Putting it all together here is the code block:
using (ExcelPackage excel = new ExcelPackage())
{
excel.Workbook.Worksheets.Add("Worksheet1");
excel.Workbook.Worksheets.Add("Worksheet2");
excel.Workbook.Worksheets.Add("Worksheet3");
var headerRow = new List<string[]>()
{
new string[] { "ID", "First Name", "Last Name", "DOB" }
};
// Determine the header range (e.g. A1:D1)
string headerRange = "A1:" + Char.ConvertFromUtf32(headerRow[0].Length + 64) + "1";
// Target a worksheet
var worksheet = excel.Workbook.Worksheets["Worksheet1"];
// Popular header row data
worksheet.Cells[headerRange].LoadFromArrays(headerRow);
FileInfo excelFile = new FileInfo(@"C:UsersamirDesktoptest.xlsx");
excel.SaveAs(excelFile);
}
If we open the file in Excel, we see that the header row appears in the first worksheet:
Row Styling
We can easily change the font size, color, and weight of any row.
worksheet.Cells[headerRange].Style.Font.Bold = true;
worksheet.Cells[headerRange].Style.Font.Size = 14;
worksheet.Cells[headerRange].Style.Font.Color.SetColor(System.Drawing.Color.Blue);
Add Data to Specific Cell
We can easily add data to a cell by setting the Value property of the Cell element.
worksheet.Cells["A1"].Value = "Hello World!";
Add Data to Multiple Cells
Inserting data into multiple cells is also straightforward. We can populate a list containing an array that corresponds to each row.
var cellData= new List()
{
new object[] {0, 0, 0, 1},
new object[] {10,7.32,7.42,1},
new object[] {20,5.01,5.24,1},
new object[] {30,3.97,4.16,1},
new object[] {40,3.97,4.16,1},
new object[] {50,3.97,4.16,1},
new object[] {60,3.97,4.16,1},
new object[] {70,3.97,4.16,1},
new object[] {80,3.97,4.16,1},
new object[] {90,3.97,4.16,1},
new object[] {100,3.97,4.16,1}
};
excelWorksheet.Cells[2, 1].LoadFromArrays(cellData);
Here we add the data from cellData into the worksheet starting on row 2, column 1. Remember that we already inserted a header row on row 1.
Check if Excel is installed
We can use this line of code to determine if Excel is installed:
bool isExcelInstalled = Type.GetTypeFromProgID("Excel.Application") != null ? true : false;
If the expression evaluates to true, then we can safely open the file using the below code:
if (isExcelInstalled)
{
System.Diagnostics.Process.Start(excelFile.ToString());
}
What about Microsoft.Office.Interop.Excel?
If the user has Excel installed on their machine, we could tap into the Microsoft.Office.Interop.Excel assembly which instructs .NET on how to call the Excel COM libraries.
This approach has a couple flaws though. Excel file generation would fail if the user didn’t have Excel installed. Also, what happens when the version of the assembly we’re using is incompatible with the latest version of Excel?
A software application shouldn’t rely on an Excel installation in order to create a spreadsheet which is why I discourage using Microsoft.Office.Interop.Excel.
You can use a library called ExcelLibrary. It’s a free, open source library posted on Google Code:
ExcelLibrary
This looks to be a port of the PHP ExcelWriter that you mentioned above. It will not write to the new .xlsx format yet, but they are working on adding that functionality in.
It’s very simple, small and easy to use. Plus it has a DataSetHelper that lets you use DataSets and DataTables to easily work with Excel data.
ExcelLibrary seems to still only work for the older Excel format (.xls files), but may be adding support in the future for newer 2007/2010 formats.
You can also use EPPlus, which works only for Excel 2007/2010 format files (.xlsx files). There’s also NPOI which works with both.
There are a few known bugs with each library as noted in the comments. In all, EPPlus seems to be the best choice as time goes on. It seems to be more actively updated and documented as well.
Also, as noted by @АртёмЦарионов below, EPPlus has support for Pivot Tables and ExcelLibrary may have some support (Pivot table issue in ExcelLibrary)
Here are a couple links for quick reference:
ExcelLibrary — GNU Lesser GPL
EPPlus — GNU (LGPL) — No longer maintained
EPPlus 5 — Polyform Noncommercial — Starting May 2020
NPOI — Apache License
Here some example code for ExcelLibrary:
Here is an example taking data from a database and creating a workbook from it. Note that the ExcelLibrary code is the single line at the bottom:
//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);
Creating the Excel file is as easy as that. You can also manually create Excel files, but the above functionality is what really impressed me.
- Download source — 397.15 KB
Introduction
Microsoft Excel is widely used in business because it offers the ability to present data to business executives in a way that makes sense to them. In this article, we are going to learn how easy it is to create an Excel document using C#.
Background
While looking to find an easy solution of how to read and write into a spreadsheet, I came across an article on the Microsoft site, How To Use ADO.NET to Retrieve and Modify Records in Excel. This is a wonderful article; however, formatting the data and the cosmetics of the document is not possible using this approach.
Using the Code
In order to use the class, you must add as a reference the Microsoft Excel XX.X Object Library in your project; this is a COM component; adding in Visual Studio is straight forward. Right click on your project on the Solution explorer and you should see the add reference option. Once selected, click the COM tab and look for the Excel library.
Once added, cut and paste the class below:
using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace ExcelExample { class CreateExcelDoc { private Excel.Application app = null; private Excel.Workbook workbook = null; private Excel.Worksheet worksheet = null; private Excel.Range workSheet_range = null; public CreateExcelDoc() { createDoc(); } public void createDoc() { try { app = new Excel.Application(); app.Visible = true; workbook = app.Workbooks.Add(1); worksheet = (Excel.Worksheet)workbook.Sheets[1]; } catch (Exception e) { Console.Write("Error"); } finally { } } public void createHeaders(int row, int col, string htext, string cell1, string cell2, int mergeColumns,string b, bool font,int size,string fcolor) { worksheet.Cells[row, col] = htext; workSheet_range = worksheet.get_Range(cell1, cell2); workSheet_range.Merge(mergeColumns); switch(b) { case "YELLOW": workSheet_range.Interior.Color = System.Drawing.Color.Yellow.ToArgb(); break; case "GRAY": workSheet_range.Interior.Color = System.Drawing.Color.Gray.ToArgb(); break; case "GAINSBORO": workSheet_range.Interior.Color = System.Drawing.Color.Gainsboro.ToArgb(); break; case "Turquoise": workSheet_range.Interior.Color = System.Drawing.Color.Turquoise.ToArgb(); break; case "PeachPuff": workSheet_range.Interior.Color = System.Drawing.Color.PeachPuff.ToArgb(); break; default: break; } workSheet_range.Borders.Color = System.Drawing.Color.Black.ToArgb(); workSheet_range.Font.Bold = font; workSheet_range.ColumnWidth = size; if (fcolor.Equals("")) { workSheet_range.Font.Color = System.Drawing.Color.White.ToArgb(); } else { workSheet_range.Font.Color = System.Drawing.Color.Black.ToArgb(); } } public void addData(int row, int col, string data, string cell1, string cell2,string format) { worksheet.Cells[row, col] = data; workSheet_range = worksheet.get_Range(cell1, cell2); workSheet_range.Borders.Color = System.Drawing.Color.Black.ToArgb(); workSheet_range.NumberFormat = format; } } }
Let’s Go Over the Class
The first thing we do is declare the variables that are responsible for creating an Excel document.
private Excel.Application app = null;
creates the Excel documentprivate Excel.Workbook workbook = null;
create the workbook in the recently created documentprivate Excel.Worksheet worksheet = null;
allows us to work with current worksheetprivate Excel.Range workSheet_range = null;
allows us to modify cells on the sheet
Note that the variables are not initialized; since they will be initialized in the constructor.
The Class has Two Methods
The class has only two methods: createHeaders
and addData
. Both of them take almost similar arguments. The createHeaders
takes more arguments since headers must be noticeable as such. Let’s explain what the arguments are:
row,col
— They are used to tell Excel where in the cell we want the texthtext
— This variable will hold the text for the headercell1,cell2
— This will be used to specify what cells we will use, e.g. A1:B1mergeColumns
— It holds the number of cells we want to merge in a cellb
— It will hold the color of the background for the chosen cellfont
—True
orFalse
for the font of the text on the selected cellsize
— To specify the size of the cellfcolor
— Specify the color font
Below is the non-similar variable used in the addData
method:
format
— It is used to tell Excel what time of format we want
How to Use the Class
Below is an example of how to use the class and if everything goes well; you should see the spreadsheet.
CreateExcelDoc excell_app = new CreateExcelDoc(); excell_app.createHeaders(5, 2, "Total of Products", "B5", "D5", 2,"YELLOW",true,10,"n"); excell_app.createHeaders(6, 2, "Sold Product", "B6", "B6", 0, "GRAY", true,10,""); excell_app.createHeaders(6, 3, "", "C6", "C6", 0, "GRAY", true,10,""); excell_app.createHeaders(6, 4, "Initial Total", "D6", "D6", 0, "GRAY", true,10,""); excell_app.addData(7, 2, "114287", "B7", "B7","#,##0"); excell_app.addData(7, 3, "", "C7", "C7", ""); excell_app.addData(7, 4, "129121", "D7", "D7", "#,##0"); excell_app.addData(8, 2, "", "B8", "B8", ""); excell_app.addData(8, 3, "=B7/D7", "C8", "C8", "0.0%"); excell_app.addData(8, 4, "", "D8", "D8", ""); excell_app.createHeaders(9, 2, "", "B9", "D9", 2, "GAINSBORO", true, 10, "");
Enjoy it!
History
- 26th August, 2007: Initial post
Currently working as an application/web developer for a Hospital in New York City.
I also do consulting work on the side.
In this tutorial I will show you how to create an Excel file using the C# programming language. This tutorial consists of a step-by-step guide specially designed for beginners and intermediate developers. Experts can skip the “project creation” section and jump directly to the “code” section. I will use the IronXL Library to create Excel files.
We will cover the following topics:
- What is an Excel File?
- What is IronXL?
- A Step-by-Step Guide to Creating Excel Files
- Step 1: Create a Visual Studio Project
- Step 2: Install the NuGet Package
- Step 3: Create an Excel Workbook
- Step 4: Set a Default Worksheet
- Step 5: Save the Workbook
- Step 6: Set Cell Values
- Set Cell Values Manually
- Set Cell Values Dynamically
- Set Cell Values from the Database
- Summary
What is an Excel File?
Excel is a spreadsheet application developed and published by Microsoft. It is part of the Microsoft Office suite of productivity software.
Excel is a tool for both organizing data and making calculations with it. The software can analyze data, calculate statistics, generate pivot tables, and represent data as charts or graphs.
For example, you could create an Excel spreadsheet that calculates a monthly budget, tracks associated expenses, and interactively sorts the data by various criteria.
Unlike a word processor, such as Microsoft Word, Excel organizes data in columns and rows. Rows and columns intersect at a space called a cell. Each cell contains data, such as text, numerical values, or formulas.
What is IronXL?
IronXL is an intuitive C# & VB Excel API that allows you to read, edit and create Excel spreadsheet files in .NET with lightning-fast performance. There is no need to install MS Office or even Excel Interop. This library can also be used for manipulating Excel documents.
IronXL fully supports .NET Core, .NET Framework, Xamarin, Mobile, Linux, MacOS and Azure.
A Step-by-Step Guide to Creating Excel Files
Firstly, we have to create a new Visual Studio Project. I will use the Console Application template for the demonstration. You can use any template that best suits your requirements.
You may also use a current project that would benefit from the capacity to create Excel files.
Step1: Create a Visual Studio Project
Open Microsoft Visual Studio 2019 or any other version. However, the latest version is recommended. Click on “Create New Project”. Select the C# Console Application for the application template. Click on the “Next” button.
Assign a name to your project. I have named mine «Excel Tutorial». You can select any name you wish. Click the “Next” button, and set the target framework. I have set my target framework to «.Net 5.0», the latest and most stable version. Click the “Create” button, and a new project will be created for you.
(adsbygoogle = window.adsbygoogle || []).push({});
Step 2: Install the NuGet Package in Visual Studio
Our next step is to install the IronXL NuGet Package for our project. Click on “Tools” on the menu bar. A new drop-down menu will appear. Click on «NuGet Package Manager» and then «Manage Nuget Packages for Solution», as shown below.
Click on “Browse” and search for IronXL in the search bar.
Click on “IronXL.Excel” and press the “Installed” button. This will install IronXL in your project. Now you are free to use any of its functions in your project.
Now that the IronXL Library has been installed, let’s go to the next step.
Step 3: Create an Excel Workbook
Firstly, add the namespace of IronXL into your project.
using IronXL;
Enter fullscreen mode
Exit fullscreen mode
It could not be easier to create a new Excel Workbook using IronXL! We need just one line of code. Yes, really!
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
Enter fullscreen mode
Exit fullscreen mode
Both the XLS (older Excel file versions) and XLSX (current and newer file versions) file formats can be created with IronXL.
Step 4: Set a Default Worksheet
Let’s create an Excel spreadsheet. I have just created one. You can create as many Excel spreadsheets as you need.
var sheet = workbook.CreateWorkSheet("Result Sheet");
Enter fullscreen mode
Exit fullscreen mode
«Sheet» in the above code snippet represents the worksheet, and you can use it to set cell values and almost everything else Excel can do.
If you are confused about the difference between a Workbook and a Worksheet, let me explain: a Workbook contains Worksheets. This means that you can add as many Worksheets as you like into one Workbook. I will explain how to do this in a later article. A Worksheet contains rows and columns. The intersection of a row and a column is called a cell, and these cells are what we manipulate whilst working with Excel.
Step 5: Save the Workbook
To save the xlsx format Workbook, use the following code:
workbook.SaveAs("Budget.xlsx");
Enter fullscreen mode
Exit fullscreen mode
Run the program to see the output.
Output File
This program will create a new workbook. You can find it in your project bin folder. You can also specify the path with the “Save As” function. Open your Excel document with Microsoft Excel. Below is the Excel worksheet we have just created.
Step 6: Setting Cell Values
Now that our workbook is created and saved, let’s add some data to the cell.
Setting Cell Values Manually:
To set cell values manually, you simply indicate which cell you are working with and set its value, as in the following example:
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
var sheet = workbook.CreateWorkSheet("Result Sheet");
// Set Cell Values Manually
sheet["A1"].Value = "Object Oriented Programming";
sheet["B1"].Value = "Data Structure";
sheet["C1"].Value = "Database Management System";
sheet["D1"].Value = "Agile Development";
sheet["E1"].Value = "Software Design and Architecture";
sheet["F1"].Value = "Software Requirement Engineering";
sheet["G1"].Value = "Computer Programming";
sheet["H1"].Value = "Software Project Management";
sheet["I1"].Value = "Software Construction";
sheet["J1"].Value = "Software Quality Engineering";
sheet["K1"].Value = "Software ReEngineering";
sheet["L1"].Value = "Advance Database Management System";
// Save Workbook
workbook.SaveAs("Result Sheet.xlsx");
Enter fullscreen mode
Exit fullscreen mode
Here, I have populated Columns A to L, and the first row of each to the names of various courses related to software engineering.
Run the program to see the output:
Output File
Setting Cell Values Dynamically
To set values dynamically we employ instructions that are very similar to those under the previous heading. The advantage here is that you do not have to hard-code the cell location. In the next code example, you will create a new random object to create random numbers, and then make use of a loop to iterate through the range of cells you’d like to populate with values.
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
var sheet = workbook.CreateWorkSheet("Result Sheet");
/**
Set Cell Value Dynamically
**/
Random r = new Random();
for (int i = 2; i <= 11; i++)
{
sheet["A" + i].Value = r.Next(1, 100);
sheet["B" + i].Value = r.Next(1, 100);
sheet["C" + i].Value = r.Next(1, 100);
sheet["D" + i].Value = r.Next(1, 100);
sheet["E" + i].Value = r.Next(1, 100);
sheet["F" + i].Value = r.Next(1, 100);
sheet["G" + i].Value = r.Next(1, 100);
sheet["H" + i].Value = r.Next(1, 100);
sheet["I" + i].Value = r.Next(1, 100);
sheet["J" + i].Value = r.Next(1, 100);
sheet["K" + i].Value = r.Next(1, 100);
sheet["L" + i].Value = r.Next(1, 100);
}
// Save Workbook
workbook.SaveAs("Result Sheet.xlsx");
}
Enter fullscreen mode
Exit fullscreen mode
Every cell from A2 to L11 contains a unique value that was randomly generated.
Let’s run the program. It will create an excel file for us. Open this with Microsoft Excel to see the output.
Output
Talking about dynamic values, how about learning how to dynamically add data into cells directly from a database? The next code snippet quickly shows how this is done, assuming you have set up your database connections correctly.
Adding Data Directly from a Database
I will get the data from the table and assign those values to the cells of my spreadsheet. Here is a snapshot of my “Marks” table:
I will get the data from that tables and assign those values to the cells of my spreadsheet. Here is the snapshot of my Marks Table.
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
var sheet = workbook.CreateWorkSheet("Result Sheet");
//Create database objects to populate data from database
string contring;
string sql;
DataSet ds = new DataSet("ResultSet");
SqlConnection con;
SqlDataAdapter da;
//Set Database Connection string
contring = @"data source = DESKTOP-FEP5MVSSQLEXPRESS; Initial Catalog = Result; Integrated Security = True; ";
//SQL Query to obtain data
sql = "SELECT [Data Structure],[Computer Programming] , [Agile Development] , [Software ReEngineering] , [Software Construction] FROM Marks";
//Open Connection & Fill DataSet
con = new SqlConnection(contring);
da = new SqlDataAdapter(sql, con);
con.Open();
da.Fill(ds);
//Loop through Column
foreach (DataTable table in ds.Tables)
{
for (int j = 0; j < table.Columns.Count; j++)
{
sheet["A1"].Value = table.Columns[j].ToString();
sheet["B1"].Value = table.Columns[j].ToString();
sheet["C1"].Value = table.Columns[j].ToString();
sheet["D1"].Value = table.Columns[j].ToString();
sheet["E1"].Value = table.Columns[j].ToString();
}
}
//Loop through contents of dataset
foreach (DataTable table in ds.Tables)
{
for (int j = 0; j < table.Rows.Count; j++)
{
sheet["A" + (j + 2)].Value = table.Rows[j]["Data Structure"].ToString();
sheet["B" + (j + 2)].Value = table.Rows[j]["Computer Programming"].ToString();
sheet["C" + (j + 2)].Value = table.Rows[j]["Agile Development"].ToString();
sheet["D" + (j + 2)].Value = table.Rows[j]["Software ReEngineering"].ToString();
sheet["E" + (j + 2)].Value = table.Rows[j]["Software Construction"].ToString();
}
}
// Save Workbook
workbook.SaveAs("Result Sheet.xlsx");
}
Enter fullscreen mode
Exit fullscreen mode
In the above code, I first set the connection string of my database, and then I read the data from the table. Next, I assigned the column name to the Excel spreadsheet in the first loop, and values of the table in the second loop.
You simply have to set the value property of the particular cell to the field name, so that it can be entered into the cell.
Output File
Let’s run the program. It will create an Excel file for us. Open this with Microsoft Excel to see the output.
Summary
IronXL allow us to generate new Excel files in C#, create new worksheets inside them, set font sizes, use formulas and much more. There are too many functions and details to describe here. For more detailed information, please click here.
Iron software provides other libraries such as IronPdf for creating Pdf documents, Iron Barcode for generating, reading and manipulating barcode, and so forth. If you purchase the complete Iron suite, you will be eligible to receive all 5 products for the price of just two. For more details, please click here.
I hope this article was helpful and easy to read. Feel free to comment with your queries and feedback.
You can download a file project from this link.