How to insert a date to an Open XML worksheet? - c#

I'm using Microsoft Open XML SDK 2 and I'm having a really hard time inserting a date into a cell. I can insert numbers without a problem by setting Cell.DataType = CellValues.Number, but when I do the same with a date (Cell.DataType = CellValues.Date) Excel 2010 crashes (2007 too).
I tried setting the Cell.Text value to many date formats as well as Excel's date/numeric format to no avail. I also tried to use styles, removing the type attribute, plus many other pizzas I threw at the wall…
Can anyone point me to an example inserting a date to a worksheet?

I used the code provided by Andrew J, but the DataType CellValues.Date produced a corrupted xlsx-file for me.
The DataType CellValues.Number worked fine for me (Don't forget to set NumberFormatId):
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
My whole code:
DateTime valueDate = DateTime.Now;
string valueString = valueDate.ToOADate().ToString();
CellValue cellValue = new CellValue(valueString);
Cell cell = new Cell();
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.StyleIndex = yourStyle; //StyleIndex of CellFormat cfBaseDate -> See below
cell.Append(cellValue);
My CellFormat for this cell in the Stylesheet looks like:
CellFormat cfBaseDate = new CellFormat() {
ApplyNumberFormat = true,
NumberFormatId = 14, //14 is a localized short Date (d/m/yyyy) -> See list below
//Some further styling parameters
};
If you'd like to format your date another way, here is a list of all default Excel NumberFormatId's
ID FORMAT CODE
0 General
1 0
2 0.00
3 #,##0
4 #,##0.00
9 0%
10 0.00%
11 0.00E+00
12 # ?/?
13 # ??/??
14 d/m/yyyy
15 d-mmm-yy
16 d-mmm
17 mmm-yy
18 h:mm tt
19 h:mm:ss tt
20 H:mm
21 H:mm:ss
22 m/d/yyyy H:mm
37 #,##0 ;(#,##0)
38 #,##0 ;[Red](#,##0)
39 #,##0.00;(#,##0.00)
40 #,##0.00;[Red](#,##0.00)
45 mm:ss
46 [h]:mm:ss
47 mmss.0
48 ##0.0E+0
49 #
Source of list: https://github.com/ClosedXML/ClosedXML/wiki/NumberFormatId-Lookup-Table
I know this list is from ClosedXML, but it's the same in OpenXML.

When creating new SpreadsheetDocument from scratch, for Date formatting to work, minimal Stylesheet has to be created.
Critical are those few lines:
new CellFormat
{
NumberFormatId = 14,
ApplyNumberFormat = true
})
Full Stylesheet class:
using (var spreadSheet = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook))
{
// Workbook
var workbookPart = spreadSheet.AddWorkbookPart();
workbookPart.Workbook =
new Workbook(new Sheets(new Sheet { Name = "Sheet1", SheetId = (UInt32Value) 1U, Id = "rId1" }));
// Add minimal Stylesheet
var stylesPart = spreadSheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = new Stylesheet
{
Fonts = new Fonts(new Font()),
Fills = new Fills(new Fill()),
Borders = new Borders(new Border()),
CellStyleFormats = new CellStyleFormats(new CellFormat()),
CellFormats =
new CellFormats(
new CellFormat(),
new CellFormat
{
NumberFormatId = 14,
ApplyNumberFormat = true
})
};
// Continue creating `WorksheetPart`...
After Stylesheet is added, DateTime can be formatted:
if (valueType == typeof(DateTime))
{
DateTime date = (DateTime)value;
cell.CellValue = new CellValue(date.ToOADate().ToString(CultureInfo.InvariantCulture));
// "StyleIndex" is "1", because "NumberFormatId=14"
// is in the 2nd item of `CellFormats` array.
cell.StyleIndex = 1;
}
Note that StyleIndex value depends on the order of CellFormat items in the CellFormats array or the Stylesheet object. In this example NumberFormatId = 14 item on the 2nd item in the array.

You have to convert DateTime to double using function ToOADate i.e.:
DateTime dtValue = DateTime.Now;
string strValue = dtValue.ToOADate().ToString(CultureInfo.InvariantCulture);
then set it as CellValue
Cell cell;
cell.DataType = new EnumValue<CellValues>(CellValues.Date);
cell.CellValue = new CellValue(strValue);
Remember to format cell using DateTime formatting, otherwise you will see double value, not date.

There are 2 ways to store dates in OpenXml; by writing a number (using ToOADate) and setting the DataType to Number or by writing an ISO 8601 formatted date and setting the DataType to Date. Note that the default DataType is Number so if you go with the first option you don't have to set the DataType.
Whichever method you choose, you'll need to set the style as Excel displays both methods identically. The following code shows an example of writing a date using the Number format (with and without explicitly setting the DataType) and using the ISO 8601 format.
using (SpreadsheetDocument document = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
//fluff to generate the workbook etc
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet" };
sheets.Append(sheet);
workbookPart.Workbook.Save();
var sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
//add the style
Stylesheet styleSheet = new Stylesheet();
CellFormat cf = new CellFormat();
cf.NumberFormatId = 14;
cf.ApplyNumberFormat = true;
CellFormats cfs = new CellFormats();
cfs.Append(cf);
styleSheet.CellFormats = cfs;
styleSheet.Borders = new Borders();
styleSheet.Borders.Append(new Border());
styleSheet.Fills = new Fills();
styleSheet.Fills.Append(new Fill());
styleSheet.Fonts = new Fonts();
styleSheet.Fonts.Append(new Font());
workbookPart.AddNewPart<WorkbookStylesPart>();
workbookPart.WorkbookStylesPart.Stylesheet = styleSheet;
CellStyles css = new CellStyles();
CellStyle cs = new CellStyle();
cs.FormatId = 0;
cs.BuiltinId = 0;
css.Append(cs);
css.Count = UInt32Value.FromUInt32((uint)css.ChildElements.Count);
styleSheet.Append(css);
Row row = new Row();
DateTime date = new DateTime(2017, 6, 24);
/*** Date code here ***/
//write an OADate with type of Number
Cell cell1 = new Cell();
cell1.CellReference = "A1";
cell1.CellValue = new CellValue(date.ToOADate().ToString());
cell1.DataType = new EnumValue<CellValues>(CellValues.Number);
cell1.StyleIndex = 0;
row.Append(cell1);
//write an OADate with no type (defaults to Number)
Cell cell2 = new Cell();
cell2.CellReference = "B1";
cell2.CellValue = new CellValue(date.ToOADate().ToString());
cell1.StyleIndex = 0;
row.Append(cell2);
//write an ISO 8601 date with type of Date
Cell cell3 = new Cell();
cell3.CellReference = "C1";
cell3.CellValue = new CellValue(date.ToString("yyyy-MM-dd"));
cell3.DataType = new EnumValue<CellValues>(CellValues.Date);
cell1.StyleIndex = 0;
row.Append(cell3);
sheetData.AppendChild(row);
worksheetPart.Worksheet.Save();
}

Use Shared String:
// assuming it's the first item in the shared string table
SharedStringItem sharedStringItem = new SharedStringItem();
Text text = new Text();
text.Text = DateTime.Today.ToString("MM/dd/yyyy hh:mm");
sharedStringTable1.Append(sharedStringItem);
Then later in code:
// assuming it's the first item in the shared string table
var cell = new Cell {CellReference = "A1", DataType = CellValues.SharedString};
var cellValue = new CellValue("0");
cell.Append(cellValue);

The following worked for us:
c.CellValue = new CellValue(datetimeValue).ToOADate().ToString());
c.DataType = CellValues.Number;
c.StyleIndex = StyleDate;
Set the DataType to CellValues.Number and then be sure to format the cell with the appropriate style index from the CellFormats. In our case we build a stylesheet within the worksheet, and StyleDate is an index into the CellFormats in the stylesheet.

a) Get compatibility with Excel 2007, Excel 2007 Viewer etc.
b) DateTime before 1.1.1900 write as string.
DateTime dat = (DateTime)dr[dc.ColumnName];
//Not working with Excel 2007
//cell.DataType = CellValues.Date;
//cell.CellValue = new CellValue(dat.ToString("s"));
double diff = (dat - new DateTime(1899, 12, 30)).TotalSeconds / 86400.0;
if (diff > 1)
{
cell.DataType = CellValues.Number;
cell.CellValue = new CellValue(diff.ToString().Replace(",", "."));
if (dat.TimeOfDay == new TimeSpan(0))
{
cell.StyleIndex = 2; //Custom Style NumberFormatId = 14 ( d/m/yyyy)
}
else
{
cell.StyleIndex = 1; //Custom Style NumberFormatId = 22 (m/d/yyyy H:mm)
}
}
else
{
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dat.ToString());
}

Related

Formatting dates and currency when exporting to Excel

I have some code that's creating a DataTable, and then converting it to an Excel spreadsheet. Code is below:
DataTable table = (DataTable)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(exportDtos), typeof(DataTable));
using var stream = new MemoryStream();
using (SpreadsheetDocument document = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet1" };
sheets.Append(sheet);
Row headerRow = new Row();
List<String> columns = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
Row newRow = new Row();
foreach (String col in columns)
{
Cell cell = new Cell();
var celltype = dsrow[col].GetType();
if (dsrow[col].GetType() == typeof(double))
{
cell.DataType = CellValues.Number;
cell.CellValue = new CellValue(decimal.Parse(dsrow[col].ToString()));
cell.StyleIndex = 2;
}
else if (dsrow[col].GetType() == typeof(DateTime))
{
cell.DataType = CellValues.Date;
cell.CellValue = new CellValue(DateTime.Parse(dsrow[col].ToString()).ToOADate());
cell.StyleIndex = 1;
}
else
{
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dsrow[col].ToString());
}
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
workbookPart.Workbook.Save();
}
The problem is that dates and decimal values were stored as text, and not sorting correctly in Excel, so I added these two conditions:
if (dsrow[col].GetType() == typeof(double))
{
cell.DataType = CellValues.Number;
cell.CellValue = new CellValue(decimal.Parse(dsrow[col].ToString()));
cell.StyleIndex = 2;
}
else if (dsrow[col].GetType() == typeof(DateTime))
{
cell.DataType = CellValues.Date;
cell.CellValue = new CellValue(DateTime.Parse(dsrow[col].ToString()).ToOADate());
cell.StyleIndex = 1;
}
else
{
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dsrow[col].ToString());
}
There's a few problems:
The StyleIndex doesn't work for the double values, it's not formatting the cell with 2 decimal places. It also gives this Repair error:
We found a problem with some content in 'file.xlsx' ... Excel was able to open the file by repairing or removing the unreadable content.
Excel completed file level validation and repair. Some parts of this workbook may have been repaired or discarded.
If I remove the StyleIndex, I don't get the error, but it still doesn't format the cell with 2 decimal places.
The date value is always a number value, not a date. And it always gives the repair error.
I've looked at several different forums saying to try different things, and I can't get any of them to work. I've changed the StyleIndex to different suggested numbers, changed the DataType, and it's always the same problems. Is there a consistent answer to how to format dates and currency values?

How to add colour to particular excel columns based on conditions using openxml?

I'm generating an excel sheet and I want to color the excel columns based on conditions. Now my all excel columns get red colors. I want to color only particular column names.
I'm using open XML for generating excel, is there any way to find the cells to apply color
using (SpreadsheetDocument document = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
Sheet sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Template" };
sheets.Append(sheet);
var stylesheet = new Stylesheet() { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "x14ac" } };
stylesheet.AddNamespaceDeclaration("mc", "http: //schemas.openxmlformats.org/markup-compatibility/2006");
stylesheet.AddNamespaceDeclaration("x14ac", "http: //schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
var fills = new Fills() { Count = 5U };
var fonts = new Fonts() { Count = 1U, KnownFonts = true };
// var cellFormats = new CellFormats();
Font font = new Font();
font.Append(new Color() { Rgb = "ff0000" });
fonts.Append(font);
// cellFormats.AppendChild(new CellFormat() { FontId = 0U });
stylesheet.Append(fonts);
stylesheet.Append(fills);
//stylesheet.Append(cellFormats);
//stylesheet.Append(fill);
var stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = stylesheet;
stylePart.Stylesheet.Save();
workbookPart.Workbook.Save();
SheetData sheetData = worksheetPart.Worksheet.AppendChild(new SheetData());
// Constructing header
Row row = new Row();
foreach (DataExchangeDefinition a in importColList)
{
defnExist = true;
if (a.MustFieldYN == true)
{
row.Append(
ConstructCell(a.FieldCaption, CellValues.String));
}
else
{
row.Append(
ConstructCell(a.FieldCaption, CellValues.String));
}
}
if (defnExist == false)
{
row.Append(
ConstructCell("Excel Template Definition Missing", CellValues.String));
}
// Insert the header row to the Sheet Data
sheetData.AppendChild(row);
// Inserting each employee
worksheetPart.Worksheet.Save();
}
Here is construct cell method
private Cell ConstructCell(string value, CellValues dataType)
{
Cell c = new Cell()
{
CellValue = new CellValue(value),
DataType = new EnumValue<CellValues>(dataType)
//StyleIndex=0U
};
return c;
}
Is there any way to solve this?
1) Add style sheet to your WorkBookPart
WorkbookPart workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorkbookStylesPart stylePart = workbookPart.AddNewPart<WorkbookStylesPart>();
stylePart.Stylesheet = GenerateStylesheet();
stylePart.Stylesheet.Save();
Note: Add above WorkbookStylesPart code just below the WorkbookPart otherwise you can't get it to work.
2) Add below function that return stylesheet,
private Stylesheet GenerateStylesheet()
{
Stylesheet styleSheet = null;
Fonts fonts = new Fonts(
new Font( // Index 0 - default
new FontSize() { Val = 10 }
),
new Font( // Index 1 - header
new FontSize() { Val = 10 },
new Bold(),
new Color() { Rgb = "FFFFFF" }
));
Fills fills = new Fills(
new Fill(new PatternFill() { PatternType = PatternValues.None }), // Index 0 - default
new Fill(new PatternFill() { PatternType = PatternValues.Gray125 }), // Index 1 - default
new Fill(new PatternFill(new ForegroundColor { Rgb = new HexBinaryValue() { Value = "66666666" } })
{ PatternType = PatternValues.Solid }) // Index 2 - header
);
Borders borders = new Borders(
new Border(), // index 0 default
new Border( // index 1 black border
new LeftBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
new RightBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
new TopBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
new BottomBorder(new Color() { Auto = true }) { Style = BorderStyleValues.Thin },
new DiagonalBorder())
);
CellFormats cellFormats = new CellFormats(
new CellFormat(), // default
new CellFormat { FontId = 0, FillId = 0, BorderId = 1, ApplyBorder = true }, // body
new CellFormat { FontId = 1, FillId = 2, BorderId = 1, ApplyFill = true } // header
);
styleSheet = new Stylesheet(fonts, fills, borders, cellFormats);
return styleSheet;
}
3) And your ConstructCell method,
private Cell ConstructCell(string value, CellValues dataType, uint styleIndex = 0)
{
return new Cell()
{
CellValue = new CellValue(value),
DataType = new EnumValue<CellValues>(dataType),
StyleIndex = styleIndex
};
}
4) And call your above method like
If you dont want to apply style then use below
ConstructCell(a.FieldCaption, CellValues.String));
And if you want to apply style on body cell then use below
ConstructCell(a.FieldCaption, CellValues.String, 1);
And if you want to apply style on header cell then use below
ConstructCell(a.FieldCaption, CellValues.String, 2);

Issue with DateFormat in Excel while using OpenXMLWriter

I am trying to write excelsheet with data formatting. I have used the logic mentioned here https://www.codeproject.com/Articles/877791/How-to-Create-Large-Excel-File-using-Openxml
The problem I am facing is I need the date to be in UK format DD-MM-YYYY. SO I have changed
NumberingFormat nf;
nf = new NumberingFormat();
nf.NumberFormatId = iExcelIndex++;
// nf.FormatCode = #"[$-409]m/d/yy\ h:mm\ AM/PM;#";Changed this to below
nf.FormatCode = #"[$-409]dd/mm/yyyy;#";
But now the date comes out as XX-01-1900 the Month and Year are defaulting to 01 and 1900.
Would be great if someone can point me in a right direction.
The following works for me:
I am adding a date on cellRef A1
static void Main(string[] args)
{
string excelFilePath = "Test1.xlsx";
string text = "02-25-1999";
string sheetName = "Sheet1";
using (SpreadsheetDocument spreadsheetDoc = SpreadsheetDocument.Open(excelFilePath, true))
{
var stylesheet = spreadsheetDoc.WorkbookPart.WorkbookStylesPart.Stylesheet;
var numberingFormats = stylesheet.NumberingFormats;
const string dateFormatCode = "dd/mm/yyyy";
var dateFormat =
numberingFormats.OfType<NumberingFormat>()
.FirstOrDefault(format => format.FormatCode == dateFormatCode);
if (dateFormat == null)
{
dateFormat = new NumberingFormat
{
NumberFormatId = UInt32Value.FromUInt32(164),
// Built-in number formats are numbered 0 - 163. Custom formats must start at 164.
FormatCode = StringValue.FromString(dateFormatCode)
};
numberingFormats.AppendChild(dateFormat);
numberingFormats.Count = Convert.ToUInt32(numberingFormats.Count());
stylesheet.Save();
}
// get the (1-based) index
var dateStyleIndex = numberingFormats.ToList().IndexOf(dateFormat) + 1;
var worksheetPart = GetWorksheetPartByName(spreadsheetDoc, "Sheet1");
Row row1 = worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements<Row>().FirstOrDefault();
Cell cell = row1.Elements<Cell>().FirstOrDefault();
DateTime dateTime = DateTime.Parse(text);
double oaValue = dateTime.ToOADate();
cell.CellValue = new CellValue(oaValue.ToString(CultureInfo.InvariantCulture));
cell.StyleIndex = Convert.ToUInt32(dateStyleIndex);
worksheetPart.Worksheet.Save();
spreadsheetDoc.WorkbookPart.WorkbookStylesPart.Stylesheet.Save();
}
Console.ReadKey();
}
Where GetWorksheetPartByName is:
private static WorksheetPart GetWorksheetPartByName(SpreadsheetDocument document, string sheetName)
{
IEnumerable<Sheet> sheets =
document.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name == sheetName);
if (!sheets.Any())
{
// The specified worksheet does not exist.
return null;
}
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(relationshipId);
return worksheetPart;
}
Dates in excel are just number of days from the default date. Compute the number to insert and then apply the desired styling over the cell.

File format error after open downloaded excel file

In my app, I am trying to download excel file from byte array content in mvc. After file downloaded, when I open that downloaded file I am getting error.
"The file you're trying to open 'XXXX.xls' is in a different format
than specified by the file extension. Verify that the file is not
corrupted and is from a trusted source before opening the file. Do you
want to open the file now?"
after click on yes in above error I am getting another error
Excel found unreadable content in 'XXXX.xls'. Do you want to
recover the contents of this workbook? If you trust the source of this
workbook, click Yes.
Again when I am click on yes in above error message I am getting first error message again.
"The file you're trying to open 'XXXX.xls' is in a different format
than specified by the file extension. Verify that the file is not
corrupted and is from a trusted source before opening the file. Do you
want to open the file now?"
After click on yes in above error message, excel opens a repair popup showing message inside it. The message is
Repaired Records: Format from /xl/styles.xml part (Styles)
Here is my controller code
[HttpPost, FileDownload]
public FileContentResult GetReport(DateTime StartDate, DateTime EndDate, int ReportType)
{
var reportData = new Model().GetReport(StartDate, EndDate, ReportType);
string fileName = "Report " + (TimeZoneUtil.ConvertUtcDateTimeToESTDateTime(DateTime.UtcNow).ToString("yyyy:MM:dd:hh:mm:ss")) + ".xls";
return File(reportData, MimeMapping.GetMimeMapping(fileName), fileName);
}
I am calling this method in view using jQuery File Download Plugin and my code is
var dataToSend = { "StartDate": $("#dtpreportstartdate").val(), "EndDate": $("#dtpreportenddate").val(), "ReportType": value };
$.fileDownload(GetBaseUrl() + "Dashboard/GetReport",
{
preparingMessageHtml: "success message",
failMessageHtml: "Error message",
httpMethod: "POST",
data: dataToSend
});
Below is my method to get excel content
public byte[] CreateReportFile(List<BGClass> BGRows)
{
MemoryStream ms = new MemoryStream();
SpreadsheetDocument xl = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);
WorkbookPart wbp = xl.AddWorkbookPart();
WorksheetPart wsp = wbp.AddNewPart<WorksheetPart>();
Workbook wb = new Workbook();
FileVersion fv = new FileVersion();
fv.ApplicationName = "Microsoft Office Excel";
Worksheet ws = new Worksheet();
SheetData sd = new SheetData();
AddStyleSheet(ref xl);
Row headerRow = new Row();
Cell CreatedDateHeaderCell = new Cell() { StyleIndex = Convert.ToUInt32(1) };
CreatedDateHeaderCell.DataType = CellValues.String;
CreatedDateHeaderCell.CellValue = new CellValue("Created Date");
headerRow.Append(CreatedDateHeaderCell);
Cell BackgroundNameHeaderCell = new Cell() { StyleIndex = Convert.ToUInt32(1) };
BackgroundNameHeaderCell.DataType = CellValues.String;
BackgroundNameHeaderCell.CellValue = new CellValue("Bg Name");
headerRow.Append(BackgroundNameHeaderCell);
sd.Append(headerRow);
foreach (BGClass reportRow in BGRows)
{
Row dataRow = new Row();
Cell CreatedDateDataCell = new Cell();
CreatedDateDataCell.DataType = CellValues.String;
CreatedDateDataCell.CellValue = new CellValue(TimeZoneHelper.ConvertUtcDateTimeToESTDateTime(reportRow.CreatedDate).ToString());
dataRow.Append(CreatedDateDataCell);
Cell BackgroundNameDataCell = new Cell();
BackgroundNameDataCell.DataType = CellValues.String;
BackgroundNameDataCell.CellValue = new CellValue(reportRow.BackgroundName);
dataRow.Append(BackgroundNameDataCell);
}
ws.Append(sd);
wsp.Worksheet = ws;
wsp.Worksheet.Save();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = "Report";
sheet.SheetId = 1;
sheet.Id = wbp.GetIdOfPart(wsp);
sheets.Append(sheet);
wb.Append(fv);
wb.Append(sheets);
xl.WorkbookPart.Workbook = wb;
xl.WorkbookPart.Workbook.Save();
xl.Close();
return ms.ToArray();
}
What is wrong with the code? Why I am getting excel error while opening a file?
I tried lots of blog to change MIME type, but nothing work for me.
Any idea?
You're using SpreadsheetDocument.Create()from the OpenXML SDK.
This indicates that you're writing an XLSX file, yet you serve the file with an XLS extension and according MIME type.
Change the file extension to .xlsx, indicating the XML format.
Can I suggest something ?
Why not use a free C# library, like mine (link below), which you can pass your List<> variable to, and it'll create a perfectly working .xlsx file for you.
CodeProject: Export to Excel, in C#
One line of code, and this problem goes away:
public void CreateReportFile(List<BGClass> BGRows)
{
CreateExcelFile.CreateExcelDocument(BGRows, "SomeFilename.xlsx");
}
All C# source code is provided free of charge.
I solved the problem after did some research. I am applying style to header row in excel using function AddStyleSheet(ref xl);. Problem occurs in that method I missing few parameters while applying style to cell.
My old method is
private WorkbookStylesPart AddStyleSheet(ref SpreadsheetDocument spreadsheet)
{
WorkbookStylesPart stylesheet = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
Stylesheet workbookstylesheet = new Stylesheet();
Font fontBold = new Font(new FontName() { Val = "Arial" }); // Default font
Font defaultFont = new Font(new FontName() { Val = "Arial" }); // Bold font
Bold bold = new Bold();
defaultFont.Append(bold);
Fonts fonts = new Fonts(); // <APENDING Fonts>
fonts.Append(fontBold);
fonts.Append(defaultFont);
//// <Fills>
//Fill fill0 = new Fill(); // Default fill
//Fills fills = new Fills(); // <APENDING Fills>
//fills.Append(fill0);
// <Borders>
//Border border0 = new Border(); // Defualt border
//Borders borders = new Borders(); // <APENDING Borders>
//borders.Append(border0);
// <CellFormats>
CellFormat cellformat0 = new CellFormat() { FontId = 0, FillId = 0, BorderId = 0 }; // Default style : Mandatory | Style ID =0
CellFormat cellformat1 = new CellFormat() { FontId = 1 }; // Style with Bold text ; Style ID = 1
// <APENDING CellFormats>
CellFormats cellformats = new CellFormats();
cellformats.Append(cellformat0);
cellformats.Append(cellformat1);
// Append FONTS, FILLS , BORDERS & CellFormats to stylesheet <Preserve the ORDER>
workbookstylesheet.Append(fonts);
//workbookstylesheet.Append(fills);
//workbookstylesheet.Append(borders);
workbookstylesheet.Append(cellformats);
// Finalize
stylesheet.Stylesheet = workbookstylesheet;
stylesheet.Stylesheet.Save();
return stylesheet;
}
Here in this function I commented Fill and border section as I don't need it. But if you don't use it while applying style index it will give you "unreachable content" error, which I was facing.
So I changed my method and add Fill and border section to style. Here is my updated method.
private WorkbookStylesPart AddStyleSheet(ref SpreadsheetDocument spreadsheet)
{
WorkbookStylesPart stylesheet = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
Stylesheet workbookstylesheet = new Stylesheet(
new Fonts(
new Font( // Index 0 – The default font.
new FontSize() { Val = 11 },
new Color() { Rgb = new HexBinaryValue() { Value = "000000" } },
new FontName() { Val = "Arial" }),
new Font( // Index 1 – The bold font.
new Bold(),
new FontSize() { Val = 11 },
new Color() { Rgb = new HexBinaryValue() { Value = "000000" } },
new FontName() { Val = "Arial" })
),
new Fills(
new Fill( // Index 0 – The default fill.
new PatternFill() { PatternType = PatternValues.None })
),
new Borders(
new Border( // Index 0 – The default border.
new LeftBorder(),
new RightBorder(),
new TopBorder(),
new BottomBorder(),
new DiagonalBorder())
),
new CellFormats(
new CellFormat() { FontId = 0, FillId = 0, BorderId = 0 }, // Index 0 – The default cell style. If a cell does not have a style index applied it will use this style combination instead
new CellFormat() { FontId = 1, FillId = 0, BorderId = 0 } // Index 1 – Bold
)
);
stylesheet.Stylesheet = workbookstylesheet;
stylesheet.Stylesheet.Save();
return stylesheet;
}
For ref link
https://blogs.msdn.microsoft.com/chrisquon/2009/11/30/stylizing-your-excel-worksheets-with-open-xml-2-0/.

How to get value shown in cell from .xlsx using open XML C#

Im new to C# and open XML, so please be patient with my ingnorance.
I have this problem:
I need to get cell value from .xlsx file. I can do that using XlGetCellValue method.
But When one cell (for example A2 from sheet1) gets it value from another cell (B2 sheet2)
XlGetCellValue("", "Sheet1", "A2")
returns Sheet2!B2Joe.
Or when the cell contains computation (like =C2+D2), XlGetCellValue(...) returns C2+D2120
Is there any easy way to get just value "Joe" and "120?
Here the link to MSDN on how to get the value of a cell using the Open XML SDK 2.5. There is a code sample provided.
How to: Retrieve the values of cells in a spreadsheet document (Open XML SDK)
Working with openxmnl could be a pain in the ass if you haven't yet downloaded OpenXMLSDKToolV25.msi (Productivity tool).
basically it's a reflection tool. you can open an excel document and the tool create all code you need to build the same from scratch.
CellValue it's only for value. using formula you have to deal with cell formula.
Eg. I created an excel file in A1 = 1256 in B1 = 2 in C1 "=A1*B1"
Opening the file with OpenXMLSDKTool i got:
public Row GenerateRow()
{
Row row1 = new Row(){ RowIndex = (UInt32Value)1U, Spans = new ListValue<StringValue>() { InnerText = "1:3" } };
Cell cell1 = new Cell(){ CellReference = "A1" };
CellValue cellValue1 = new CellValue();
cellValue1.Text = "1256";
cell1.Append(cellValue1);
Cell cell2 = new Cell(){ CellReference = "B1" };
CellValue cellValue2 = new CellValue();
cellValue2.Text = "2";
cell2.Append(cellValue2);
Cell cell3 = new Cell(){ CellReference = "C1" };
CellFormula cellFormula1 = new CellFormula();
cellFormula1.Text = "A1*B1";
CellValue cellValue3 = new CellValue();
cellValue3.Text = "2512";
cell3.Append(cellFormula1);
cell3.Append(cellValue3);
row1.Append(cell1);
row1.Append(cell2);
row1.Append(cell3);
return row1;
}
from this you can notice that CellValue and CellFormula are both childs of Cell.
So, assuming you can retrieve your Row r you can have this:
Cell c = r.Elements<Cell>().ElementAt(2);
CellValue cv = c.CellValue;
CellFormula cf = c.CellFormula;

Categories