OpenXML library save excel file - c#

I have the following code and its not saving the values to cell and also in file. It shows value in cell.cellvalue field but its not writing it to excel. I have no idea how to save the file. I used OpenXml-SDK and I am writing datatable values to each cell/row of created spreadsheet document.
using (SpreadsheetDocument ssd=SpreadsheetDocument.Open(Server.MapPath(#"\ExcelPackageTemplate.xlsx"),true))
{
WorkbookPart wbPart = ssd.WorkbookPart;
WorksheetPart worksheetPart = wbPart.WorksheetParts.First();
SheetData sheetdata = worksheetPart.Worksheet.GetFirstChild<SheetData>();
string[] headerColumns = new string[] { dt.Columns[0].ColumnName, dt.Columns[1].ColumnName,dt.Columns[2].ColumnName };
DocumentFormat.OpenXml.Spreadsheet.Row r = new DocumentFormat.OpenXml.Spreadsheet.Row();
int RowIndexer = 1;
//int colInd=0;
r.RowIndex = (UInt32)RowIndexer;
string test = ColumnName(RowIndexer);
foreach (DataColumn dc in dt.Columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.CellReference = test+RowIndexer;
cell.DataType = CellValues.InlineString;
cell.InlineString = new InlineString(new Text(dc.ColumnName.ToString()));
DocumentFormat.OpenXml.Spreadsheet.CellValue value = new DocumentFormat.OpenXml.Spreadsheet.CellValue();
r.AppendChild(cell);
// colInd++;
}
//r.RowIndex = (UInt32)RowIndexer;
RowIndexer = 2;
foreach (DataRow dr in dt.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row Row = new DocumentFormat.OpenXml.Spreadsheet.Row();
string Index = ColumnName(RowIndexer);
Row.RowIndex = (UInt32)RowIndexer;
foreach (object value in dr.ItemArray)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = CellValues.InlineString;
cell.InlineString = new InlineString(new Text(value.ToString()));
cell.CellReference = Index+RowIndexer;
// cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(value.ToString());
Row.AppendChild(cell);
}
RowIndexer++;
}
worksheetPart.Worksheet.Save();
wbPart.Workbook.Save();
ssd.Close();

Try this:
using (SpreadsheetDocument ssd = SpreadsheetDocument.Open(Server.MapPath(#"\ExcelPackageTemplate.xlsx"), true))
{
WorkbookPart wbPart = ssd.WorkbookPart;
WorksheetPart worksheetPart = wbPart.WorksheetParts.First();
SheetData sheetdata = worksheetPart.Worksheet.GetFirstChild<SheetData>();
string[] headerColumns = new string[] { dt.Columns[0].ColumnName, dt.Columns[1].ColumnName, dt.Columns[2].ColumnName };
DocumentFormat.OpenXml.Spreadsheet.Row r = new DocumentFormat.OpenXml.Spreadsheet.Row();
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
int RowIndexer = 1;
int ColumnIndexer = 1;
r.RowIndex = (UInt32)RowIndexer;
foreach (DataColumn dc in dt.Columns)
{
cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.CellReference = ColumnName(ColumnIndexer) + RowIndexer;
cell.DataType = CellValues.InlineString;
cell.InlineString = new InlineString(new Text(dc.ColumnName.ToString()));
// consider using cell.CellValue. Then you don't need to use InlineString.
// Because it seems you're not using any rich text so you're just bloating up
// the XML.
r.AppendChild(cell);
ColumnIndexer++;
}
// here's the missing part you needed
sheetdata.Append(r);
RowIndexer = 2;
foreach (DataRow dr in dt.Rows)
{
r = new DocumentFormat.OpenXml.Spreadsheet.Row();
r.RowIndex = (UInt32)RowIndexer;
// this follows the same starting column index as your column header.
// I'm assuming you start with column 1. Change as you see fit.
ColumnIndexer = 1;
foreach (object value in dr.ItemArray)
{
cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
// I moved it here so it's consistent with the above part
// Also, the original code was using the row index to calculate
// the column name, which is weird.
cell.CellReference = ColumnName(ColumnIndexer) + RowIndexer;
cell.DataType = CellValues.InlineString;
cell.InlineString = new InlineString(new Text(value.ToString()));
r.AppendChild(cell);
ColumnIndexer++;
}
RowIndexer++;
// missing part
sheetdata.Append(r);
}
worksheetPart.Worksheet.Save();
wbPart.Workbook.Save();
ssd.Close();
}
Some comments:
The ColumnName() function is from here.
I'm assuming you wanted the column headers in a row, and data in subsequent rows (because the original code had the row index used for calculating the column name).
Cleaned up some parts of the code so it's easier to read and that the column header and data row parts are more consistent in writing style.
I suggest that you consider using CellValue instead of InlineString. Based on your code, you're importing a DataTable, and you don't seem to need rich text so InlineString's are a little overkill and might make the resulting file larger (bloated XML). Use one or the other, and remember to set DataType accordingly.
Also, the code only works for completely empty SheetData.

There are some possible issues here:
You create and add new Rows and Cells: it presumes the worksheet is totally blank when you open it (ie: no rows or cells with the same index/address).
Since you set the CellType to InlineString, you need to set the Cell.InlineString and not Cell.CellValue
cell.DataType = CellValues.InlineString;
cell.InlineString = new InlineString(New Text(value.TsString()));
Also, there is something wrong in your code concerning usage of
CellReference. These parts of code have no sense:
cell.CellReference = dc.ColumnName.ToString();
cell.CellReference = value.ToString();
Cell Address should be something like this "A1". You have to review your code to set the correct address. You already have the rowIndex. You need to get the column name. This Translate a column index into an Excel Column Name can help.

Related

C# OpenXML Changing Column Background

I have a code left by the previous developer. What I need to do is to change the background color and text color of the header columns in the Excel file. But I just couldn't. We use OpenXML. Heading columns are added as rows. I can't change background and text color of these header row. How can I change the background color of the cell interiors in the cell variable?
public byte[] analizVerileriExport(DataTable data)
{
byte[] result;
using (MemoryStream mem = new MemoryStream())
{
using (var spreadsheetDocument = SpreadsheetDocument.Create(mem, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
// Add a WorkbookPart to the document.
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart.
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
SheetData sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
// Add Sheets to the Workbook.
Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
// Append a new worksheet and associate it with the workbook.
Sheet sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.
GetIdOfPart(worksheetPart),
SheetId = 1,
Name = string.IsNullOrEmpty(data.TableName) ? "Analiz Verileri" : data.TableName
};
Row headerRow = new Row();
List<excelColumns> columns = new List<excelColumns>();
foreach (DataColumn column in data.Columns)
{
columns.Add(new excelColumns() { columnName = column.ColumnName, columnDataType = column.DataType });
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in data.Rows)
{
Row newRow = new Row();
foreach (excelColumns col in columns)
{
Cell cell = new Cell();
cell.DataType = col.columnDataType.ToCellValue();
cell.CellValue = new CellValue(dsrow[col.columnName].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
sheets.Append(sheet);
workbookpart.Workbook.Save();
// Close the document.
spreadsheetDocument.Close();
}
result = mem.ToArray();
}
//string excelName = cmbClient.Text + " Kişisel Veri Envanteri " + String.Format("{0:dd_MM_yyyy HH-mm-ss}", DateTime.Now) + ".xlsx";
//openFile(excelName, result);
return result;
}

How can I fit all columns on one page in a spreadsheet?

I have exported the report to Excel and it works fine, but when I print the file the width of the spreadsheet doesn't fit all column into one page. For this to happen I have to change the Page Layout, and set the scaling to fit 1 on width and 43 tall. How can I get this from code?
using (var workbook = SpreadsheetDocument.Create(Savepath, SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new Workbook();
workbook.WorkbookPart.Workbook.Sheets = new Sheets();
//declare our MergeCells here
MergeCells mergeCells = null;
foreach (DataRow dsrow in table.Rows)
{
int innerColIndex = 0;
rowIndex++;
Row newRow = new Row();
foreach (String col in columns)
{
Stylesheet stylesheet1 = new Stylesheet();
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dsrow[col].ToString());
cell.CellReference = excelColumnNames[innerColIndex] + rowIndex.ToString();
if (table.TableName == "Work Order Report")
{
string cellNameWorkOrder = dsrow[col].ToString();
if (cellNameWorkOrder == "POSTER: 10% MUST HAVE APPROACH AND CLOSE-UP SHOTS - PHOTO OF EACH CREATIVE" || cellNameWorkOrder == "BULLETINS: 100% CLOSE-UP AND APPROACH OF EACH UNIT")
{
if (mergeCells == null)
mergeCells = new MergeCells();
var cellAddress = cell.CellReference;
var cellAddressTwo = "I" + rowIndex.ToString();
mergeCells.Append(new MergeCell() { Reference = new StringValue(cellAddress + ":" + cellAddressTwo) });
}
}
newRow.AppendChild(cell);
innerColIndex++;
}
sheetData.AppendChild(newRow);
}
//add the mergeCells to the worksheet if we have any
if (mergeCells != null)
sheetPart.Worksheet.InsertAfter(mergeCells, sheetPart.Worksheet.Elements<SheetData>().First());
}
workbook.WorkbookPart.Workbook.Save();
}
The excel report looks like https://www.screencast.com/t/CCMR96Mw7u when I print now its like https://www.screencast.com/t/MkTpDc98RD0l ,https://www.screencast.com/t/MRyzpEiFICM the expected result is https://www.screencast.com/t/ztgvm6mISSwp
In order to achieve this you need to do two things. Firstly, you need to add a PageSetupProperties instance to a SheetProperties instance which in turn should get added to your Worksheet. The PageSetupProperties has a FitToPage property which is the part that sets the radio button in Excel to "Fit to".
Next, you need to use the PageSetup class in order to set the width and height required. This is done via the FitToWidth and FitToHeight properties. The PageSetup also needs to be added to the Worksheet.
Note that the order of the elements is important, you can see the correct order in the ECMA spec.
The following is a self contained example that adds one cell and then sets the properties the way that you need them:
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookpart = myDoc.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart.
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
SheetData sheetData = new SheetData();
//add a row
Row row = new Row();
row.RowIndex = 1;
//create a cell
Cell cell = new Cell();
cell.CellReference = "A1";
CellValue cellValue = new CellValue();
cellValue.Text = "123";
cell.Append(cellValue);
row.AppendChild(cell);
sheetData.AppendChild(row);
// Add a WorkbookPart to the document.
worksheetPart.Worksheet = new Worksheet(sheetData);
//this sets the "Fit to" radio in Excel.
//note this must come before the SheetData
SheetProperties sheetProperties = new SheetProperties();
PageSetupProperties pageSetupProperties = new PageSetupProperties() { FitToPage = true };
sheetProperties.Append(pageSetupProperties);
worksheetPart.Worksheet.InsertBefore(sheetProperties, sheetData);
// this changes the fit to width and height
PageSetup pageSetup = new PageSetup() { FitToWidth = 1, FitToHeight = 43 };
worksheetPart.Worksheet.AppendChild(pageSetup);
//append the sheets / sheet
Sheets sheets = myDoc.WorkbookPart.Workbook.AppendChild(new Sheets());
sheets.AppendChild(new Sheet()
{
Id = myDoc.WorkbookPart.GetIdOfPart(myDoc.WorkbookPart.WorksheetParts.First()),
SheetId = 1,
Name = "Sheet1"
});
}

How can we specify the columns DataType to string, number Datetime in Excel/SpreadSheet when Export from c#

am using the following code to export the data to Excel from c#. I will Provide one sample image with this to know better what i needed.
NOt only for a single column we cannot say this type is coming to a particular column in excel. during exporting of diffrent data
the code am using is
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.
Create(savingFileName, SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart to the document.
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
// Add a WorksheetPart to the WorkbookPart.
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
var bold1 = new System.Windows.Documents.Bold();
DocumentFormat.OpenXml.Spreadsheet.CellFormat cf = new DocumentFormat.OpenXml.Spreadsheet.CellFormat();
// Add Sheets to the Workbook.
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets;
sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>(new DocumentFormat.OpenXml.Spreadsheet.Sheets());
// Append a new worksheet and associate it with the workbook.
var sheet = new Sheet()
{
Id = spreadsheetDocument.WorkbookPart.
GetIdOfPart(worksheetPart),
SheetId = sheetId,
Name = "Sheet" + sheetId
};
sheets.Append(sheet);
//Add Header Row.
var headerRow = new Row();
headerRow.RowIndex = 10;
var cell=new Cell();
foreach (DataColumn column in dtCollection.Columns)
{
cell = new Cell
{
DataType = CellValues.String, CellValue = new CellValue(column.ColumnName.ToUpper())
};
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow row in dtCollection.Rows)
{
var newRow = new Row();
foreach (DataColumn col in dtCollection.Columns)
{
cell = new Cell
{
DataType = CellValues.String,
CellValue = new CellValue(row[col].ToString())
};
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
workbookpart.Workbook.Save();
spreadsheetDocument.Close();
The image is as Follows
in this above pic you can see Debit and credit column it should be number but with my code it can be only string
Column Type
Credit-Number
Debit-Number
Date- Date-time
Code-String
opening Balance-Number
with the above requirement i need to export the datatable to excel in excel each column should be differnt datatype. how can i do this can any one help me to complete my work
Ok then here are two options I can come up quickly.
If you have few options of column choice, then map columnName <--> NumberFormat
If you have too much column possibility, then map primitiveType <--> NumberFormat (However you can only have one floating format for i.e. all Decimal columns, regardless of the business need of the specific column)
Here is an example for first option: Use a dictionary to lookup which number format you should inject into each column.
var headerFormatMap = new Dictionary<string, string>(); // <columnHeader, NumberFormat>
// i.e fill it like this
headerFormatMap.Add("TransactionDate", "MM/DD/YYYY");
headerFormatMap.Add("Debit", "##.000"); // Display 37.75 as 37.750.
Give formatting of all your possible columns like this. And when the time comes to export, get the correct numberFormat and inject it to its column:
// Assuming your first row is header. (I remember excel indexes start from 1)
// Do this foreach column
Range range = (Excel.Range)worksheetobject.Cells[1,1];
var header = (string)range.Value;
range.EntireColumn.NumberFormat = headerFormatMap[header];

Apply OpenXML excel number formatcode to string value in C#

Using OpenXML in C#, does anybody knows how to apply an excel number formatcode - for instance (* #,##0.00);(* (#,##0.00);(* "-"??);(#_) - to a string value?
Example, if I have a value "10.52982" I should obtain "10.53"
Thanks
PS I don't want to use the Microsoft.Office.Interop.Excel assembly which provides WorksheetFunction.Text function
Try this:
//Create Document
SpreadsheetDocument googleSpreadSheet = SpreadsheetDocument.Create(GoogleSpreadhSheetStream, SpreadsheetDocumentType.Workbook);
WorkbookPart cWorkbookPart = googleSpreadSheet.AddWorkbookPart();
//Create stylesheet
WorkbookStylesPart spStyles = cWorkbookPart.AddNewPart<WorkbookStylesPart>();
spStyles.Stylesheet = new Stylesheet();
spStyles.Stylesheet.NumberingFormats = new NumberingFormats();
uint iExcelIndex = 164;
//Create format
NumberingFormat nf2decimal = new NumberingFormat();
nf2decimal.NumberFormatId = UInt32Value.FromUInt32(3453);//UInt32Value.FromUInt32(iExcelIndex++);
nf2decimal.FormatCode = StringValue.FromString("0.00");
spStyles.Stylesheet.NumberingFormats.Append(nf2decimal);
//Create cellFormat
CellFormat numFormat = new CellFormat();
numFormat.FormatId = 0;
numFormat.FillId = 0;
numFormat.BorderId = 0;
numFormat.FormatId = 0;
numFormat.NumberFormatId = nf2decimal.NumberFormatId;
numFormat.ApplyNumberFormat = BooleanValue.FromBoolean(true);
//Apped cellformat for cells
spStyles.Stylesheet.CellFormats.AppendChild<CellFormat>(cellFormat);
//update styles and format count
spStyles.Stylesheet.NumberingFormats.Count = UInt32Value.FromUInt32((uint)spStyles.Stylesheet.NumberingFormats.ChildElements.Count);
spStyles.Stylesheet.CellFormats.Count = UInt32Value.FromUInt32((uint)spStyles.Stylesheet.CellFormats.ChildElements.Count);
//save the changes to the stylesheet
spStyles.Stylesheet.Save();
googleSpreadSheet.WorkbookPart.Workbook.Save();
And when setting the value of the cell, use the format index. Since I just added one, the format index should be 1
SheetData cSheetData = (SheetData)GetWorkSheet(sheetId).Where(x => x.LocalName == "sheetData").First();
Row currentRow = new Row();
Cell cell = new Cell();
currentRow.RowIndex = Convert.ToUInt32(cSheetData.ChildElements.Count()) + 1;
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.CellValue = new CellValue(value.Value);
cell.StyleIndex = 1;
cell.CellReference = nextCol + rowIndex;
currentRow.AppendChild(cell);
cSheetData.Append(currentRow);
GetWorkSheet(sheetId).Save(); //this returns the reference to my sheet doc to save it
Hope this helps you out

Export DataTable to Excel with Open Xml SDK in c#

My program have ability to export some data and DataTable to Excel file (template)
In the template I insert the data to some placeholders. It's works very good, but I need to insert a DataTable too...
My sample code:
using (Stream OutStream = new MemoryStream())
{
// read teamplate
using (var fileStream = File.OpenRead(templatePath))
fileStream.CopyTo(OutStream);
// exporting
Exporting(OutStream);
// to start
OutStream.Seek(0L, SeekOrigin.Begin);
// out
using (var resultFile = File.Create(resultPath))
OutStream.CopyTo(resultFile);
Next method to exporting
private void Exporting(Stream template)
{
using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
{
// Replace shared strings
SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
IEnumerable<Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<Text>();
DoReplace(sharedStringTextElements);
// Replace inline strings
IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
foreach (var worksheet in worksheetParts)
{
DoReplace(worksheet.Worksheet.Descendants<Text>());
}
int z = 40;
foreach (System.Data.DataRow row in ExcelWorkXLSX.ToOut.Rows)
{
for (int i = 0; i < row.ItemArray.Count(); i++)
{
ExcelWorkXLSX.InsertText(workbook, row.ItemArray.ElementAt(i).ToString(), getColumnName(i), Convert.ToUInt32(z)); }
z++;
}
}
}
}
But this fragment to output DataTable slooooooooooooooooooooooowwwwwww...
How can I export DataTable to Excel fast and truly?
I wrote this quick example. It works for me. I only tested it with one dataset with one table inside, but I guess that may be enough for you.
Take into consideration that I treated all cells as String (not even SharedStrings). If you want to use SharedStrings you might need to tweak my sample a bit.
Edit: To make this work it is necessary to add WindowsBase and DocumentFormat.OpenXml references to project.
Enjoy,
private void ExportDataSet(DataSet ds, string destination)
{
using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
foreach (System.Data.DataTable table in ds.Tables) {
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (System.Data.DataColumn column in table.Columns) {
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (System.Data.DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
eburgos, I've modified your code slightly because when you have multiple datatables in your dataset it was just overwriting them in the spreadsheet so you were only left with one sheet in the workbook. I basically just moved the part where the workbook is created out of the loop. Here is the updated code.
private void ExportDSToExcel(DataSet ds, string destination)
{
using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
uint sheetId = 1;
foreach (DataTable table in ds.Tables)
{
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
I also wrote a C#/VB.Net "Export to Excel" library, which uses OpenXML and (more importantly) also uses OpenXmlWriter, so you won't run out of memory when writing large files.
Full source code, and a demo, can be downloaded here:
Export to Excel
It's dead easy to use.
Just pass it the filename you want to write to, and a DataTable, DataSet or List<>.
CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx");
And if you're calling it from an ASP.Net application, pass it the HttpResponse to write the file out to.
CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx", Response);
I wrote my own export to Excel writer because nothing else quite met my needs. It is fast and allows for substantial formatting of the cells. You can review it at
https://openxmlexporttoexcel.codeplex.com/
I hope it helps.
You could try taking a look at this libary. I've used it for one of my projects and found it very easy to work with, reliable and fast (I only used it for exporting data).
http://epplus.codeplex.com/
You can have a look at my library here. Under the documentation section, you will find how to import a data table.
You just have to write
using (var doc = new SpreadsheetDocument(#"C:\OpenXmlPackaging.xlsx")) {
Worksheet sheet1 = doc.Worksheets.Add("My Sheet");
sheet1.ImportDataTable(ds.Tables[0], "A1", true);
}
Hope it helps!
I tried accepted answer and got message saying generated excel file is corrupted when trying to open. I was able to fix it by doing few modifications like adding below line end of the code.
workbookPart.Workbook.Save();
I have posted full code # Export DataTable to Excel with Open XML in c#
I wanted to add this answer because I used the primary answer from this question as my basis for exporting from a datatable to Excel using OpenXML but then transitioned to OpenXMLWriter when I found it to be much faster than the above method.
You can find the full details in my answer in the link below. My code is in VB.NET though, so you'll have to convert it.
How to export DataTable to Excel

Categories

Resources