Introduction
I needed to generate a nicely formatted spreadsheet from DataSet content and I gathered code from several sources to build this project.
This is a sample spreadsheet generated:

In the project, I included an MVC page that download the generated file automatically clicking on a button using simple Ajax post.
After downloading the project, make sure to right-click in the solution and restore nuget packages.
Background
I merged a lot of code. I am including all the links below for reference:
Autofit Content:
https://social.msdn.microsoft.com/Forums/office/en-US/28aae308-55cb-479f-9b58-d1797ed46a73/solution-how-to-autofit-excel-content?forum=oxmlsdk
Coloring Cells:
https://social.msdn.microsoft.com/Forums/office/en-US/a973335c-9f9b-4e70-883a-02a0bcff43d2/coloring-cells-in-excel-sheet-using-openxml-in-c?forum=oxmlsdk
Date Formats:
https://stackoverflow.com/questions/2792304/how-to-insert-a-date-to-an-open-xml-worksheet
Auto filter:
https://community.dynamics.com/crm/b/crmmitchmilam/archive/2010/11/04/openxml-worksheet-adding-autofilter
Font Bold:
https://stackoverflow.com/questions/29913094/how-to-make-excel-work-sheet-header-row-bold-using-openxml
Generating Spreadsheet from Dataset:
http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
Download Excel file via AJAX MVC:
https://stackoverflow.com/questions/16670209/download-excel-file-via-ajax-mvc
Using the Code
Generating the spreadsheet is very simple with one line of code, provide the DataSet
, the full path of the spreadsheet file and if autofilters should be enabled or not:
CreateExcelFile.CreateExcelDocument(dataSet, fullPath, includeAutoFilter: true);
Points of Interest
I optimized the original spreadsheet generation code to avoid finding rows in the spreadsheet and cache the existing rows, this improved a lot the time to generate the spreadsheet with a bigger amount of rows and columns.
This is the code that finds the biggest text for all rows in each column, then calculate the correct size of the column:
int numberOfColumns = dt.Columns.Count;
Columns columns = new Columns();
for (int colInx = 0; colInx < numberOfColumns; colInx++)
{
DataColumn col = dt.Columns[colInx];
string maxText = col.ColumnName;
foreach (DataRow dr in dt.Rows)
{
string value = string.Empty;
if (col.DataType.FullName == "System.DateTime")
{
DateTime dtValue;
if (DateTime.TryParse(dr[col].ToString(), out dtValue))
value = dtValue.ToShortDateString();
}
else
{
value = dr[col].ToString();
}
if (value.Length > maxText.Length)
{
maxText = value;
}
}
double width = GetWidth("Calibri", 11, maxText);
columns.Append(CreateColumnData((uint)colInx + 1, (uint)colInx + 1, width+2));
}
worksheetPart.Worksheet.Append(columns);
...
private static double GetWidth(string font, int fontSize, string text)
{
System.Drawing.Font stringFont = new System.Drawing.Font(font, fontSize);
return GetWidth(stringFont, text);
}
private static double GetWidth(System.Drawing.Font stringFont, string text)
{
System.Drawing.Size textSize = System.Windows.Forms.TextRenderer.MeasureText(text, stringFont);
double width = (double)(((textSize.Width / (double)7) * 256) - (128 / 7)) / 256;
width = (double)decimal.Round((decimal)width + 0.2M, 2);
return width;
}
This is the JavaScript that downloads the spreadsheet when called:
function downloadSpreadsheet() {
$.ajax({
type: "POST",
url: '/Home/GenerateSpreadsheet',
success: function (data) {
if (data != null && (data.errorMessage == null || data.errorMessage === "")) {
if (data.fileName != "") {
window.location.href = "DownloadSpreadsheet/?file=" + data.fileName;
}
} else {
alert("An error ocurred", data.errorMessage);
}
}
});
}
It will call two MVC controllers, one to generate the spreadsheet and another to download it:
[HttpPost]
public JsonResult GenerateSpreadsheet()
{
var path = Server.MapPath("~/temp");
var fileName = "Spreadsheet.xlsx";
if (Directory.Exists(path) == false)
{
Directory.CreateDirectory(path);
}
DataSet dataSet = new DataSet("Hospital");
dataSet.Tables.Add(Table());
string fullPath = Path.Combine(path, fileName);
CreateExcelFile.CreateExcelDocument(dataSet, fullPath, includeAutoFilter: true);
return Json(new { fileName = fileName, errorMessage = "" });
}
[HttpGet]
[NoCache]
public ActionResult DownloadSpreadsheet(string file)
{
string fullPath = Path.Combine(Server.MapPath("~/temp"), file);
return File(fullPath, "application/vnd.ms-excel", file);
}
History
I started development 31 years from now, since MSX basic. Started Windows programming with VB 2.0 and Web programming with ASP 3.0. Then I built Windows Forms, Web Applications, NT services and WPF applications using Microsoft.NET. I am MCP in Visual Basic 6.0, MCAD and MCSD.NET in Framework 1.1, MCPD Web in Framework 2.0, MCTS in .NET 3.5 workflow, MCTS in .NET 3.5 communication foundation, windows presentation foundation and MVC applications. Currently working with MVC Web Application and WCF services using Micro Services architecture proposed by me. Besides programming I love running, swimming, cats and movies.