I got that code from OpenXML sdk and instead of SpreadsheetDocument.Create, I used SpreadsheetDocument.Open
This code is working and add an image in .xlsx, after image added to the file. I open the file which shows ->
The file is corrupt and cannot be opened
If you want more details Please! let me know.
Reference URL -> https://code.msdn.microsoft.com/office/How-to-insert-image-into-93964561
Thanks for the help!
/// <summary>
/// add sheet in xlsx then add image into it.
/// </summary>
/// <param name="sFile"></param>
/// <param name="imageFileName"></param>
public void InsertimginExcel(string sFile, string imageFileName)
{
try
{
// Create a spreadsheet document by supplying the filepath.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.
Open(sFile, true))
{
// Add a WorkbookPart to the document.
//WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
//workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart.
WorksheetPart worksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new 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 = "mySheet"
};
sheets.Append(sheet);
var drawingsPart = worksheetPart.AddNewPart<DrawingsPart>();
if (!worksheetPart.Worksheet.ChildElements.OfType<DocumentFormat.OpenXml.Spreadsheet.Drawing>().Any())
{
worksheetPart.Worksheet.Append(new DocumentFormat.OpenXml.Spreadsheet.Drawing { Id = worksheetPart.GetIdOfPart(drawingsPart) });
}
if (drawingsPart.WorksheetDrawing == null)
{
drawingsPart.WorksheetDrawing = new WorksheetDrawing();
}
var worksheetDrawing = drawingsPart.WorksheetDrawing;
var imagePart = drawingsPart.AddImagePart(ImagePartType.Jpeg);
using (var stream = new FileStream(imageFileName, FileMode.Open))
{
imagePart.FeedData(stream);
}
Bitmap bm = new Bitmap(imageFileName);
DocumentFormat.OpenXml.Drawing.Extents extents = new DocumentFormat.OpenXml.Drawing.Extents();
var extentsCx = (long)bm.Width * (long)((float)914400 / bm.HorizontalResolution);
var extentsCy = (long)bm.Height * (long)((float)914400 / bm.VerticalResolution);
bm.Dispose();
var colOffset = 0;
var rowOffset = 0;
int colNumber = 5;
int rowNumber = 10;
var nvps = worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>();
var nvpId = nvps.Count() > 0 ?
(UInt32Value)worksheetDrawing.Descendants<Xdr.NonVisualDrawingProperties>().Max(p => p.Id.Value) + 1 :
1U;
var oneCellAnchor = new Xdr.OneCellAnchor(
new Xdr.FromMarker
{
ColumnId = new Xdr.ColumnId((colNumber - 1).ToString()),
RowId = new Xdr.RowId((rowNumber - 1).ToString()),
ColumnOffset = new Xdr.ColumnOffset(colOffset.ToString()),
RowOffset = new Xdr.RowOffset(rowOffset.ToString())
},
new Xdr.Extent { Cx = extentsCx, Cy = extentsCy },
new Xdr.Picture(
new Xdr.NonVisualPictureProperties(
new Xdr.NonVisualDrawingProperties { Id = nvpId, Name = "Picture " + nvpId, Description = imageFileName },
new Xdr.NonVisualPictureDrawingProperties(new A.PictureLocks { NoChangeAspect = true })
),
new Xdr.BlipFill(
new A.Blip { Embed = drawingsPart.GetIdOfPart(imagePart), CompressionState = A.BlipCompressionValues.Print },
new A.Stretch(new A.FillRectangle())
),
new Xdr.ShapeProperties(
new A.Transform2D(
new A.Offset { X = 0, Y = 0 },
new A.Extents { Cx = extentsCx, Cy = extentsCy }
),
new A.PresetGeometry { Preset = A.ShapeTypeValues.Rectangle }
)
),
new Xdr.ClientData()
);
worksheetDrawing.Append(oneCellAnchor);
//workbookpart.Workbook.Save();
// Close the document.
spreadsheetDocument.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//log.Error("error occur while creating sheet and adding image --> " + ex.Message.ToString());
}
}
Not sure how many workbookparts and worksheetparts a xlsx file can handle and if the SheetId must be document unique for all Sheets. Try changing the Id to e.g. 5 if that does not help: do not create a new workbookpart for the sheet, use existig one, if possible.
The file is corrupt and cannot be opened
Uncheck all the options under Protected View and confirm by pressing OK.
Restart Excel and try to open the broken Excel documents.
Ref: https://answers.microsoft.com/en-us/office/forum/office_2010-excel/the-file-is-corrupt-and-cannot-be-opened-error-on/93af59c1-946c-4f5f-83c1-bd6f58dbd94f
If that doesn't work, typically when you create XSLX files and there is an error, you see this:
Can you check your Temporary Internet Files for the log. The log file should have info on what is malformed. Please update your question with any additional info.
Related
I'm working on a small excel export. All the data is there but adding a spreadsheet table for the range in question to provide quick and easy access to sort&filter when the user opens the file in excel causes a problem. The problem is that when the file is opened in excel we found a problem with some content in... and a query if they should try to recover as much as we can.
After repairing it excel states that it was able to open the file by repairing or removing the unreadable content. with Repaired Records: Table from /xl/tables/table1.xml part (Table) listed in a text field below. After this the workbook behaves as I intended, with a table.
I have searched and tried almost everything I've stumbled upon. This SO question is very similar but the proposed answer does not work for me.
A minimal example with the problem is here. It generates two excel files, one with the table added and one without. The one without is previewable in Explorer, the problematic one displays the message:
The file can't be previewed because of an error in the Microsoft Excel previewer.
Nuget used: DocumentFormat.OpenXml version 2.14.0. Excel version is office365, desktop version. Running under Windows 10.
What I have tried:
Various openxml validation tools, no errors found
Saved the (by excel) repaired file and compared the content of those two. I don't find any difference that in my head can serve as an explanation
It would be very nice to have the table already in place when the excel file is generated.
Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using ExcelGenerator;
namespace ConsoleAppOpenXmlSpreadsheetWithTable
{
class Program
{
static void Main(string[] args)
{
var headerRow = new List<string> { "Company", "Country", "Fruit" };
var exportRowList = new List<ExcelExportRow>();
exportRowList.Add(new ExcelExportRow() { Company ="Spanish Oranges A", Country = "Spain", Fruit ="Oranges"});
exportRowList.Add(new ExcelExportRow() { Company = "Mexican Oranges Ltd", Country = "Mexico", Fruit = "Oranges" });
exportRowList.Add(new ExcelExportRow() { Company = "Medit. Bananas", Country = "Spain", Fruit = "Bananas" });
exportRowList.Add(new ExcelExportRow() { Company = "Mexican Bananas", Country = "Mexico", Fruit = "Bananas" });
exportRowList.Add(new ExcelExportRow() { Company = "Mexican Sweet Oranges", Country = "Mexico", Fruit = "Oranges" });
using (var memoryStream = ExcelFileGenerator.GenerateArticleListWithImagesExcelFile(headerRow, exportRowList, false))
{
using (var fileStream = new FileStream("OpenXmlSpreadsheet.xlsx", FileMode.Create))
{
memoryStream.CopyTo(fileStream);
}
}
using (var memoryStream = ExcelFileGenerator.GenerateArticleListWithImagesExcelFile(headerRow, exportRowList, true))
{
using (var fileStream = new FileStream("OpenXmlSpreadsheetWithTable.xlsx", FileMode.Create))
{
memoryStream.CopyTo(fileStream);
}
}
}
}
}
ExcelFileGenerator.cs
using System;
using System.Collections.Generic;
using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace ExcelGenerator
{
public class ExcelExportRow
{
public string Company { get; set; }
public string Country { get; set; }
public string Fruit { get; set; }
}
public static class ExcelFileGenerator
{
private const int normalFontStyleIndex = 0;
private const int boldFontStyleIndex = 1;
public static MemoryStream GenerateArticleListWithImagesExcelFile(List<string> headerRow, List<ExcelExportRow> excelExportRoListw, bool insertTable)
{
MemoryStream memoryStream = new MemoryStream();
using (SpreadsheetDocument document = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = document.AddWorkbookPart();
Workbook workbook = new Workbook();
workbookPart.Workbook = workbook;
WorkbookStylesPart workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>("rIdStyles");
Stylesheet stylesheet = StyleSheet();
workbookStylesPart.Stylesheet = stylesheet;
workbookStylesPart.Stylesheet.Save();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
Sheets sheets = new Sheets();
//get the string name of the columns
string[] excelColumnNamesTitle = new string[5];
for (int n = 0; n < 5; n++)
excelColumnNamesTitle[n] = GetExcelColumnName(n);
var columns = new Columns();
columns.Append(new Column() { Min = 1, Max = 1, CustomWidth = true, Width = 24 });
columns.Append(new Column() { Min = 2, Max = 3, CustomWidth = true, Width = 12 });
worksheet.Append(columns);
if (excelExportRoListw is not null)
{
Row rowTitle = new Row() { RowIndex = (UInt32Value)1 };
for (int c = 0; c < headerRow.Count; c++)
{
AppendTextCell(excelColumnNamesTitle[c], headerRow[c], rowTitle, boldFontStyleIndex);
}
sheetData.Append(rowTitle);
uint rowNumber = 2;
foreach (var excelExportRow in excelExportRoListw)
{
var spreadsheetRow = new Row() { RowIndex = (UInt32Value)rowNumber };
AppendTextCell(excelColumnNamesTitle[0], excelExportRow.Company, spreadsheetRow, normalFontStyleIndex);
AppendTextCell(excelColumnNamesTitle[2], excelExportRow.Country, spreadsheetRow, normalFontStyleIndex);
AppendTextCell(excelColumnNamesTitle[3], excelExportRow.Fruit, spreadsheetRow, normalFontStyleIndex);
sheetData.Append(spreadsheetRow);
rowNumber++;
}
worksheet.Append(sheetData);
worksheetPart.Worksheet = worksheet;
}
// Table
if (insertTable)
DefineTable(worksheetPart, 1, 1 + excelExportRoListw.Count, 0, 2);
// Wrap up and save
worksheetPart.Worksheet.Save();
Sheet sheet = new Sheet() { Name = "Export", SheetId = (UInt32Value)1, Id = workbookPart.GetIdOfPart(worksheetPart) };
sheets.Append(sheet);
workbook.Append(sheets);
workbook.Save();
document.Close();
}
memoryStream.Position = 0;
return memoryStream;
}
private static void DefineTable(WorksheetPart worksheetPart, int rowMin, int rowMax, int colMin, int colMax)
{
#region Table
string rangeReference = $"{GetExcelColumnName(colMin)}{rowMin}:{GetExcelColumnName(colMax)}{rowMax}";
int tableNo = 1;
Table table = new Table()
{
Id = (UInt32)tableNo,
Name = "Table" + tableNo,
DisplayName = "Table" + tableNo,
Reference = rangeReference,
TotalsRowShown = false
};
AutoFilter autoFilter = new AutoFilter() { Reference = rangeReference };
TableColumns tableColumns = new TableColumns() { Count = (UInt32)(colMax - colMin + 1) };
for (int i = 0; i < (colMax - colMin + 1); i++)
{
tableColumns.Append(new TableColumn() { Id = (UInt32)(i + 1), Name = "Column" + i });
}
TableStyleInfo tableStyleInfo = new TableStyleInfo()
{
Name = "TableStyleMedium1",
ShowFirstColumn = false,
ShowLastColumn = false,
ShowRowStripes = true,
ShowColumnStripes = false
};
table.Append(autoFilter);
table.Append(tableColumns);
table.Append(tableStyleInfo);
#endregion
string tableRefId = "rIdTable1";
// Add table to worksheet - two different things implictly linked by using the same refId
TableDefinitionPart tableDefinitionPart = worksheetPart.AddNewPart<TableDefinitionPart>(tableRefId);
tableDefinitionPart.Table = table;
TableParts tableParts = new TableParts();
TablePart tablePart = new TablePart() { Id = tableRefId };
tableParts.Append(tablePart);
tableParts.Count = 1;
worksheetPart.Worksheet.Append(tableParts);
}
#region Excel Helper funcs
private static void AppendTextCell(string cellReference, string cellStringValue, Row excelRow, UInt32Value styleIndex)
{
// Add a new Excel Cell to our Row
Cell cell = new Cell() { CellReference = cellReference, DataType = CellValues.String };
CellValue cellValue = new CellValue();
cellValue.Text = cellStringValue;
cell.StyleIndex = styleIndex;
cell.Append(cellValue);
excelRow.Append(cell);
}
private static string GetExcelColumnName(int columnIndex)
{
if (columnIndex < 26)
return ((char)('A' + columnIndex)).ToString();
char firstChar = (char)('A' + (columnIndex / 26) - 1);
char secondChar = (char)('A' + (columnIndex % 26));
return string.Format("{0}{1}", firstChar, secondChar);
}
#endregion Helper funcs
#region Stylesheet
private static Stylesheet StyleSheet()
{
Stylesheet styleSheet = new Stylesheet();
Fonts fonts = new Fonts();
// 0 - normal fonts
Font myFont = new Font()
{
FontSize = new FontSize() { Val = 11 },
Color = new Color() { Rgb = HexBinaryValue.FromString("FF000000") },
FontName = new FontName() { Val = "Arial" }
};
fonts.Append(myFont);
//1 - font bold
myFont = new Font()
{
Bold = new Bold(),
FontSize = new FontSize() { Val = 11 },
Color = new Color() { Rgb = HexBinaryValue.FromString("FF000000") },
FontName = new FontName() { Val = "Arial" }
};
fonts.Append(myFont);
Fills fills = new Fills();
//default fill
Fill fill = new Fill()
{
PatternFill = new PatternFill() { PatternType = PatternValues.None }
};
fills.Append(fill);
Borders borders = new Borders();
//normal borders
Border border = new Border()
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
};
borders.Append(border);
CellFormats cellFormats = new CellFormats();
//0- normalFontStyleIndex for normal cells
CellFormat cellFormat = new CellFormat()
{
FontId = 0,
FillId = 0,
BorderId = 0,
ApplyFill = false
};
cellFormats.Append(cellFormat);
//1 - boldFontStyleIndex for header row
cellFormat = new CellFormat()
{
FontId = 1,
FillId = 0,
BorderId = 0,
ApplyFill = false
};
cellFormats.Append(cellFormat);
styleSheet.Append(fonts);
styleSheet.Append(fills);
styleSheet.Append(borders);
styleSheet.Append(cellFormats);
TableStyles tableStyles = new TableStyles()
{
Count = 0,
DefaultTableStyle = "TableStyleMedium1",
DefaultPivotStyle = "PivotStyleLight16"
};
styleSheet.Append(tableStyles);
return styleSheet;
}
#endregion Stylesheet
}
}
The following method creates a new workbook, and inserts two validator dropdowns:
public static void ForValidator() {
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Create("validator output.xlsx", SpreadsheetDocumentType.Workbook)) {
WorkbookPart workbookpart = myDoc.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
SheetData sheetData_ = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData_);
Sheets sheets_ = myDoc.WorkbookPart.Workbook.AppendChild(new Sheets());
sheets_.AppendChild(new Sheet() {
Id = myDoc.WorkbookPart.GetIdOfPart(myDoc.WorkbookPart.WorksheetParts.First()), SheetId = 1, Name = "Sheet1"
});
DataValidations dataValidations = new DataValidations();
DataValidation dataValidation = new DataValidation() {
Type = DataValidationValues.List, AllowBlank = true, SequenceOfReferences = new ListValue<StringValue>() { InnerText = "F2:F3" }
};
Formula1 formula = new Formula1();
formula.Text = "\"Selection 1,Selection 2,Selection 3\"";
dataValidation.Append(formula);
dataValidations.Append(dataValidation);
worksheetPart.Worksheet.AppendChild(dataValidations);
}
}
Can the same routine be modified to instead just open an existing "validator output.xlsx" file and do the same thing?
For over a week I've tried everything I know to try and have come up with nothing. Thank you for any help.
I am trying to create a simple excel file with multiple sheets using open xml, unfortunately the file does not open after it's being created.
After the file is generated, when I open it with Microsoft Excel it says
We found a problem, do you want to recover as much as we can?
using (SpreadsheetDocument spreedDoc = SpreadsheetDocument.Create(filePath,
DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
WorkbookPart wbPart = spreedDoc.WorkbookPart;
wbPart = spreedDoc.AddWorkbookPart();
wbPart.Workbook = new Workbook();
Sheets sheets = wbPart.Workbook.AppendChild(new Sheets());
foreach (var sheetData in excelSheetData)
{
// Add a blank WorksheetPart.
WorksheetPart worksheetPart = wbPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
string relationshipId = wbPart.GetIdOfPart(worksheetPart);
// Get a unique ID for the new worksheet.
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
// Give the new worksheet a name.
string sheetNameToWrite = sheetName;
if (string.IsNullOrWhiteSpace(sheetNameToWrite))
{
sheetNameToWrite = "Sheet"+sheetId;
}
// Append the new worksheet and associate it with the workbook.
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = sheetName };
sheets.AppendChild(sheet);
}
//wbPart.Workbook.Sheets.AppendChild(sheet);
wbPart.Workbook.Save();
}
On trying to Repair in excel gives below message
-<repairedRecords summary="Following is a list of repairs:">
<repairedRecord>Repaired Records: Worksheet properties from /xl/workbook.xml part (Workbook)</repairedRecord>
</repairedRecords>
</recoveryLog>
Have you seen this?
http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
The necessary steps to create a functional excel file with multiple worksheets in OpenXML (that work for me) are as follows:
using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook))
{
spreadsheet.AddWorkbookPart();
spreadsheet.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
spreadsheet.WorkbookPart.Workbook.Append(new BookViews(new WorkbookView()));
WorkbookStylesPart workbookStylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>("rIdStyles");
Stylesheet stylesheet = new Stylesheet();
workbookStylesPart.Stylesheet = stylesheet;
workbookStylesPart.Stylesheet.Save();
for (int worksheetNo = 1; worksheetNo < worksheetCountYouWantToCreate; worksheetNo++)
{
string workSheetID = "rId" + worksheetNo;
string worksheetName = "worksheet" + worksheetNo;
WorksheetPart newWorksheetPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet();
newWorksheetPart.Worksheet.AppendChild(new DocumentFormat.OpenXml.Spreadsheet.SheetData());
// write data here
// ...
// ...
newWorksheetPart.Worksheet.Save();
if (worksheetNo == 1)
spreadsheet.WorkbookPart.Workbook.AppendChild(new DocumentFormat.OpenXml.Spreadsheet.Sheets());
spreadsheet.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>().AppendChild(new DocumentFormat.OpenXml.Spreadsheet.Sheet()
{
Id = spreadsheet.WorkbookPart.GetIdOfPart(newWorksheetPart),
SheetId = (uint)worksheetNo,
Name = worksheetName
});
}
spreadsheet.WorkbookPart.Workbook.Save();
}
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/.
What im trying to do is create multiple worksheets within a work book using datasets the code i have to create a sheet data object from a data set is:
public static SheetData CreateDataSheet(DataSet ds)
{
var xlSheetData = new SheetData();
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
var tbl = ds.Tables[0];
foreach (DataRow row in tbl.Rows)
{
var xlRow = new Row();
foreach (DataColumn col in tbl.Columns)
{
var cellData = row[col];
Cell xlCell = null;
if (cellData != null)
{
xlCell = new Cell(new InlineString(new Text(cellData.ToString())))
{
DataType = CellValues.InlineString
};
}
else
{
xlCell = new Cell(new InlineString(new Text(String.Empty)))
{
DataType = CellValues.InlineString
};
}
xlRow.Append(xlCell);
}
xlSheetData.Append(xlRow);
}
}
return xlSheetData;
}
Then to create the spreadsheet and append the above to the spreadsheet i have:
public static void CreateSpreadsheetWorkbook(string filepath, List<SheetData> sd)
{
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
foreach (var x in sd)
{
var newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(x);
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
uint sheetId = 1;
if (sheets.Elements<Sheet>().Any())
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
var sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(newWorksheetPart), SheetId = sheetId, Name = "mySheet" + sheetId };
sheets.Append(sheet);
workbookpart.Workbook.Save();
}
spreadsheetDocument.Close();
}
This runs with out any errors however when i come to open the document its unable to be opened because it is corrupt.
EDIT - final working version:
public static void CreateSpreadsheetWorkbook(string filepath, List<SheetData> sd)
{
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
foreach (var x in sd)
{
var newWorksheetPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(x);
sheets = spreadsheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>();
uint sheetId = 1;
if (sheets.Elements<Sheet>().Any())
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
var sheet = new Sheet() { Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(newWorksheetPart), SheetId = sheetId, Name = "mySheet" + sheetId };
sheets.Append(sheet);
workbookpart.Workbook.Save();
}
spreadsheetDocument.Close();
}
After comparing with some similar code of mine I found these possible problems:
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook);
//should be
var spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.DocumentType);
And
var sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
//should be
var sheets = spreadsheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>();
after the first time since by the second time you already have a Sheets element.
See this blogpost for more details:
http://blogs.msdn.com/b/brian_jones/archive/2009/02/19/how-to-copy-a-worksheet-within-a-workbook.aspx