I am getting error 'Excel found unreadable content in APPL_1.xlsx.'
What is wrong in my code?.
Record contain around 2 lacks data. I am trying to fetch it from datatable to excel.
I am using OpenXMLSpreedsheetDocument to fetch data from datatable to excel
FileInfo FileLoc = new FileInfo(FilePath);
if (FileLoc.Exists)
{
FileLoc.Delete();
FileLoc = new FileInfo(FilePath);
}
SpreadsheetDocument spreadSheet = SpreadsheetDocument.
Create(FilePath, SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart to the document.
WorkbookPart workbookpart = spreadSheet.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart.
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
var bold1 = new Bold();
CellFormat cf = new CellFormat();
// Add Sheets to the Workbook.
Sheets sheets;
sheets = spreadSheet.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
// Append a new worksheet and associate it with the workbook.
var sheet = new Sheet()
{
Id = spreadSheet.WorkbookPart.
GetIdOfPart(worksheetPart),
SheetId = 0,
Name = "Sheet" + 0
};
sheets.Append(sheet);
//Add Header Row.
var headerRow = new Row();
foreach (DataColumn column in dt.Columns)
{
var cell = new Cell
{
DataType = CellValues.String,
CellValue = new CellValue(column.ColumnName)
};
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow row in dt.Rows)
{
var newRow = new Row();
foreach (DataColumn col in dt.Columns)
{
Cell c = new Cell();
c.DataType = new EnumValue<CellValues>(CellValues.String);
c.CellValue = new CellValue(row[col].ToString());
newRow.Append(c);
}
sheetData.AppendChild(newRow);
}
workbookpart.Workbook.Save();
ProcessStartInfo startInfo = new ProcessStartInfo(FilePath);
Process.Start(startInfo);
Any suggestions is much appreciated..!!
Here is my implementation of OpenXML. For simplicity, I have excluded the cell styling code.
This creates an excel file with two rows and 3 columns. You can modify this to suit your needs.
Main method:
static void Main(string[] args)
{
var dtToXl = new DtToExcel();
var dt = new DataTable();
dt.Columns.Add("Col1");
dt.Columns.Add("Col2");
dt.Columns.Add("Col3");
dt.Rows.Add("R1C1", "R1C2", "R1C3");
dt.Rows.Add("R2C1", "R2C2", "R2C3");
dtToXl.GetExcel(dt);
if(Debugger.IsAttached)
{
Console.ReadLine();
}
}
GetExcel method:
public void GetExcel(DataTable dt)
{
using (var document = SpreadsheetDocument.Create("C:\\Desktop\\Excel1.xlsx", SpreadsheetDocumentType.Workbook))
{
var workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
var sheets = workbookPart.Workbook.AppendChild(new Sheets());
AddWorksheet(dt, 1, ref sheets, ref workbookPart);
}
}
AddWorksheet method:
private void AddWorksheet(DataTable dt, int sheetCount, ref Sheets sheets, ref WorkbookPart workbookPart)
{
var worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
var sheetName = $"Sheet{sheetCount}";
worksheetPart.Worksheet = new Worksheet();
//Create header rows
#region Excel Headers
Row row = new Row
{
RowIndex = 1
};
row.AppendChild(AddCellWithValue("Column 1", CellValues.InlineString));
row.AppendChild(AddCellWithValue("Column 2", CellValues.InlineString));
row.AppendChild(AddCellWithValue("Column 3", CellValues.InlineString));
sheetData.AppendChild(row);
#endregion
//Create data rows
#region Excel data rows
var rowIndex = (UInt32)2;
foreach (DataRow dtRow in dt.Rows)
{
row = new Row
{
RowIndex = rowIndex++
};
row.AppendChild(AddCellWithValue(dtRow[0].ToString(), CellValues.InlineString));
row.AppendChild(AddCellWithValue(dtRow[1].ToString(), CellValues.InlineString));
row.AppendChild(AddCellWithValue(dtRow[2].ToString(), CellValues.InlineString));
sheetData.AppendChild(row);
}
#endregion
var columns = new Columns();
columns.Append(new Column() { Min = 1, Max = 1, Width = 20, CustomWidth = true });
columns.Append(new Column() { Min = 2, Max = 2, Width = 20, CustomWidth = true });
columns.Append(new Column() { Min = 3, Max = 3, Width = 20, CustomWidth = true });
worksheetPart.Worksheet.Append(columns);
worksheetPart.Worksheet.Append(sheetData); //This line should be anywhere below .Append(columns)
var sheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = (UInt32)sheetCount, Name = sheetName };
sheets.Append(sheet);
}
AddCellWithValue method
private Cell AddCellWithValue(string value, CellValues type)
{
var cell = new Cell
{
DataType = type
};
if (type == CellValues.InlineString)
{
var inlineString = new InlineString();
var t = new Text
{
Text = value
};
inlineString.AppendChild(t);
cell.AppendChild(inlineString);
}
else
{
cell.CellValue = new CellValue(value);
}
return cell;
}
I have used SpreadsheetLight.
Here is my code.
using SpreadsheetLight;
SLDocument sl = new SLDocument();
int iStartRowIndex = 1;
int iStartColumnIndex = 1;
sl.ImportDataTable(iStartRowIndex, iStartColumnIndex, dt, true);
// + 1 because the header row is included
// - 1 because it's a counting thing, because the start row is counted.
int iEndRowIndex = iStartRowIndex + dt.Rows.Count + 1 - 1;
// - 1 because it's a counting thing, because the start column is counted.
int iEndColumnIndex = iStartColumnIndex + dt.Columns.Count - 1;
SLTable table = sl.CreateTable(iStartRowIndex, iStartColumnIndex, iEndRowIndex, iEndColumnIndex);
table.SetTableStyle(SLTableStyleTypeValues.Medium17);
table.HasTotalRow = true;
table.SetTotalRowFunction(5, SLTotalsRowFunctionValues.Sum);
sl.InsertTable(table);
sl.SaveAs(FilePath);
sl.Dispose();
ProcessStartInfo startInfo = new ProcessStartInfo(FilePath);
Process.Start(startInfo);
Related
I am trying to create an application that can extract a ton of data from a txt file 3000+ lines.
I have already filtered the data etc and I am able to write everything into the excel spreadsheet in the correct way. My problem is that I want to split the data over multiple sheets and limit each sheet to a specific number of data rows (The exact value is a number chosen between 100-1000)
I have ended up with an output that creates the correct number of sheets, but it outputs all the lines of data into all the sheets instead of splitting them up over all the sheets.
For clarity:
Example: I have 950 lines of data. Thus the output should be 100 data rows in 8 sheets and the 9th should have the last 50.
What I currently get is: 950 data rows in all 9 sheets.
Here is my code that controls the Excel creation.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filename, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
var workSheet = worksheetPart.Worksheet;
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
for (int i = 0; i < Amount; i++)
{
Sheet sheet = new Sheet()
{
Id = workbookPart.GetIdOfPart(worksheetPart),
SheetId = ((uint)(i + 1)),
Name = "Data" + (i + 1)
};
sheets.Append(sheet);
var HeadRow = workSheet.GetFirstChild<SheetData>().AppendChild(new Row());//new Row
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Type"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Description"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Time"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Date"), DataType = new EnumValue<CellValues>(CellValues.String) });
for (int j = 0 + (i * (int)OrgAmount); j < ((i + 1) * (int)OrgAmount); j++)//Rows
{
if (j == LineCount)
{
break;
}
var row = workSheet.GetFirstChild<SheetData>().AppendChild(new Row());//new Row
var cell1 = row.AppendChild(new Cell());//Type
var cell2 = row.AppendChild(new Cell());//Description
var cell3 = row.AppendChild(new Cell());//Time
var cell4 = row.AppendChild(new Cell());//Date
cell1.CellValue = new CellValue(LineType[j]);
cell1.DataType = new EnumValue<CellValues>(CellValues.String);
cell2.CellValue = new CellValue(LineDesc[j]);
cell2.DataType = new EnumValue<CellValues>(CellValues.String);
cell3.CellValue = new CellValue(LineTime[j]);
cell3.DataType = new EnumValue<CellValues>(CellValues.String);
cell4.CellValue = new CellValue(LineDate[j]);
cell4.DataType = new EnumValue<CellValues>(CellValues.String);
}
workbookPart.Workbook.Save();
}
spreadsheetDocument.Close();
}
Please help me since I don't know where I messed up.
I got it fixed myself in the end.
Here is what I did:
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filename, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
//Create workbook, workbookPart and sheets
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
for (int i = 0; i < Amount; i++)
{
//New worksheetPart, worksheet and sheet for each sheet to be addressed seperately
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet(new SheetData());
var workSheet = worksheetPart.Worksheet;
//Dynamically create a sheet according to options chosen in form
Sheet sheet = new Sheet()
{
Id = workbookPart.GetIdOfPart(worksheetPart),
SheetId = ((uint)(i + 1)),
Name = "Data" + (i + 1)
};
//Header row creation
var HeadRow = workSheet.GetFirstChild<SheetData>().AppendChild(new Row());//new Row
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Type"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Description"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Time"), DataType = new EnumValue<CellValues>(CellValues.String) });
HeadRow.AppendChild(new Cell() { CellValue = new CellValue("Date"), DataType = new EnumValue<CellValues>(CellValues.String) });
for (int j = 0 + (i * (int)OrgAmount); j < ((i + 1) * (int)OrgAmount); j++)//Rows
{
if (j == LineCount)//If final line is reached before loop end, then break loop
{
break;
}
//Initialise new row cells
var row = workSheet.GetFirstChild<SheetData>().AppendChild(new Row());//new Row
var cell1 = row.AppendChild(new Cell());//Type
var cell2 = row.AppendChild(new Cell());//Description
var cell3 = row.AppendChild(new Cell());//Time
var cell4 = row.AppendChild(new Cell());//Date
//Write data to cells, extracted from text file
cell1.CellValue = new CellValue(LineType[j]);
cell1.DataType = new EnumValue<CellValues>(CellValues.String);
cell2.CellValue = new CellValue(LineDesc[j]);
cell2.DataType = new EnumValue<CellValues>(CellValues.String);
cell3.CellValue = new CellValue(LineTime[j]);
cell3.DataType = new EnumValue<CellValues>(CellValues.String);
cell4.CellValue = new CellValue(LineDate[j]);
cell4.DataType = new EnumValue<CellValues>(CellValues.String);
}
sheets.Append(sheet);//Append the written sheet to workbook sheets
}
workbookPart.Workbook.Save();//save workbook
spreadsheetDocument.Close();//Close document
}
So i want to add a sheet to an exisiting XLSX and it seems to work but on opening it gives an error and excel needs to repair it, i tried looking with the open xml productivity tool but couldn't find anything that looked out of place
public static void ExportExcel(string Query, string targetFileName, Boolean Overwrite, string Sheet) {
FileInfo fi = new FileInfo(targetFileName);
string filePath = fi.DirectoryName;
string fileName = fi.Name;
if (filePath == string.Empty || fileName == string.Empty) {
throw new Exception(string.Format("{0}: is invalid", targetFileName));
}
if (fi.Exists == true && !Overwrite) {
bfirst = true;
//throw new Exception("File already exists, and OverwriteIfExists was specified as false.");
}
if (fi.Exists == true && Overwrite == true) {
fi.Delete();
}
if (bfirst == false) {
using (SpreadsheetDocument document = SpreadsheetDocument.Create(targetFileName, SpreadsheetDocumentType.Workbook)) {
using (SqlConnection conn = new SqlConnection(_sqlConnStr)) {
SqlDataAdapter da = new SqlDataAdapter(Query, conn);
DataSet ds = new DataSet();
da.Fill(ds, "Q1");
DataTable table = ds.Tables["Q1"];
var workbookPart = document.AddWorkbookPart();
document.WorkbookPart.Workbook = new Workbook();
document.WorkbookPart.Workbook.Sheets = new Sheets();
var sheetPart = document.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
//Autofit comes first – we calculate width of columns based on data
sheetPart.Worksheet = new Worksheet();
SheetViews sheetViews1 = new SheetViews();
SheetView sheetView1 = new SheetView() { TabSelected = true, WorkbookViewId = (UInt32Value)0U };
Pane pane1 = new Pane() { VerticalSplit = 1D, TopLeftCell = "A2", ActivePane = PaneValues.BottomLeft, State = PaneStateValues.Frozen };
sheetView1.Append(pane1);
sheetViews1.Append(sheetView1);
sheetPart.Worksheet.Append(sheetViews1);
sheetPart.Worksheet.Append(AutoFit_Columns(table));
sheetPart.Worksheet.Append(sheetData);
//Adding styles to worksheet
Worksheet_Style(document);
Sheets sheets = document.WorkbookPart.Workbook.GetFirstChild<Sheets>();
string relationshipId = document.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0) {
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = Sheet };
sheets.Append(sheet);
Row headerRow = new Row(); //Adding column headers
for (int col = 0; col < table.Columns.Count; col++) {
Cell cell = new Cell {
DataType = CellValues.String,
CellValue = new CellValue(table.Columns[col].ColumnName.ToString()),
StyleIndex = 1// bold font
};
headerRow.AppendChild(cell);
}
// Add the row values to the excel sheet
sheetData.AppendChild(headerRow);
for (int row = 0; row < table.Rows.Count; row++) {
Row newRow = new Row();
for (int col = 0; col < table.Columns.Count; col++) {
Cell cell = new Cell();
//ommited for readability
}
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
} else {
//Add a New Sheet to the newly created .xlsx file
AddSheet(targetFileName,
Query,
Sheet);
}
}
private static void AddSheet(string targetFileName, string Query, string Sheet) {
using (SqlConnection conn = new SqlConnection(_sqlConnStr)) {
SqlDataAdapter da = new SqlDataAdapter(Query, conn);
DataSet ds = new DataSet();
da.Fill(ds, "Q1");
DataTable table = ds.Tables["Q1"];
using (SpreadsheetDocument document = SpreadsheetDocument.Open(targetFileName, true)) {
WorksheetPart sheetPart = document.WorkbookPart.AddNewPart<WorksheetPart>();
sheetPart.Worksheet = new Worksheet();
Sheets sheets = document.WorkbookPart.Workbook.GetFirstChild<Sheets>();
string relationshipId = document.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0) {
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
//Autofit comes first – we calculate width of columns based on data
var sheetData = new SheetData();
//sheetPart.Worksheet = new Worksheet();
SheetViews sheetViews1 = new SheetViews();
SheetView sheetView1 = new SheetView() { TabSelected = true, WorkbookViewId = sheetId };
Pane pane1 = new Pane() { VerticalSplit = 1D, TopLeftCell = "A2", ActivePane = PaneValues.BottomLeft, State = PaneStateValues.Frozen };
sheetView1.Append(pane1);
sheetViews1.Append(sheetView1);
sheetPart.Worksheet.Append(sheetViews1);
sheetPart.Worksheet.Append(AutoFit_Columns(table));
sheetPart.Worksheet.Append(sheetData);
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = Sheet + "_" + sheetId };
sheet.AddNamespaceDeclaration("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
sheets.Append(sheet);
//Can only add one stylesheet
//Worksheet_Style(document);
Row headerRow = new Row(); //Adding column headers
for (int col = 0; col < table.Columns.Count; col++) {
Cell cell = new Cell {
DataType = CellValues.String,
CellValue = new CellValue(table.Columns[col].ColumnName.ToString()),
StyleIndex = 1// bold font
};
headerRow.AppendChild(cell);
}
// Add the row values to the excel sheet
sheetData.AppendChild(headerRow);
for (int row = 0; row < table.Rows.Count; row++) {
Row newRow = new Row();
for (int col = 0; col < table.Columns.Count; col++) {
Cell cell = new Cell();
//ommited for readability
}
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
The first part of the code generates the xlsx which is fine and opens normally, but when i run the program again to add a second sheet, it does all that but excel doesn't like the way i did it apparently and says it needs to repair it this is the error log from excel
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<logFileName>error116880_01.xml</logFileName>
<summary>Er zijn fouten aangetroffen in bestand \file1.xlsx</summary>
<removedFeatures><removedFeature>Verwijderde functie: Weergave van het onderdeel /xl/worksheets/sheet2.xml</removedFeature></removedFeatures>
</recoveryLog>
This causes the error, my question is how can i also freeze the the top row on the second tab
SheetViews sheetViews1 = new SheetViews();
SheetView sheetView1 = new SheetView() { TabSelected = true, WorkbookViewId = sheetId };
Pane pane1 = new Pane() { VerticalSplit = 1D, TopLeftCell = "A2", ActivePane = PaneValues.BottomLeft, State = PaneStateValues.Frozen };
sheetView1.Append(pane1);
sheetViews1.Append(sheetView1);
sheetPart.Worksheet.Append(sheetViews1);
This line
SheetView sheetView1 = new SheetView() { TabSelected = true, WorkbookViewId = sheetId };
should have been
SheetView sheetView1 = new SheetView() { WorkbookViewId = (UInt32Value)0U };
That fixed it
I need help.
I have a question to ask using OpenXMLWriter.
I am currently using the code below to create my excel file, but I want to set up width of the columns and freeze panes. How should I do it?
Because I have written the following code for that. I do not know why is not working.
Example would be very helpful. Appreciate it and Thanks!
public bool ExportData(DataSet ds, string destination, List<Tuple<string, string>> parms)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(destination, SpreadsheetDocumentType.Workbook))
{
WorkbookPart wbp = spreadsheetDocument.AddWorkbookPart();
WorksheetPart wsp = wbp.AddNewPart<WorksheetPart>();
Workbook wb = new Workbook();
FileVersion fv = new FileVersion();
fv.ApplicationName = "Microsoft Office Excel";
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
foreach (DataTable table in ds.Tables)
{
Row headerRow = new Row();
int lp = 1;
foreach (var parm in parms)
{
Row newRow = new Row();
// Write the parameter names
Cell parmNameCell = new Cell();
parmNameCell.DataType = CellValues.String;
parmNameCell.CellValue = new CellValue(parm.Item1.ToString()); //
parmNameCell.StyleIndex = 1;
newRow.AppendChild(parmNameCell);
// Write the parameter values
Cell parmValCell = new Cell();
parmValCell.DataType = CellValues.InlineString;
parmValCell.DataType = CellValues.String;
parmValCell.CellValue = new CellValue(parm.Item2?.ToString()); //
newRow.AppendChild(parmValCell);
sheetData.AppendChild(newRow);
lp++;
}
Columns columns = new Columns();
int i = 1;
foreach (DataColumn column in table.Columns)
{
Column column1 = new Column();
column1.Min = Convert.ToUInt32(i);
column1.Max = Convert.ToUInt32(i);
column1.Width = insertSpaceBeforeUpperCAse(column.ColumnName).Length + 2;
column1.BestFit = true;
columns.Append(column1);
i++;
}
worksheet.Append(columns);
int freezeRow = lp;
Row blankRow = new Row();
sheetData.AppendChild(blankRow);
//// Write the column names
List<string> columns2 = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns2.Add(column.ColumnName);
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(insertSpaceBeforeUpperCAse(column.ColumnName));
cell.StyleIndex = 1;
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
Row newRow = new Row();
foreach (string col in columns2)
{
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
//worksheet.Append(sheetData);
//wsp.Worksheet = worksheet;
//wsp.Worksheet.Save();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = table.TableName;
sheet.SheetId = 1;
sheet.Id = wbp.GetIdOfPart(wsp);
sheets.Append(sheet);
wb.Append(fv);
wb.Append(sheets);
#region Freeze Panel
string freezeRangeFrom = $"A{freezeRow + 2}";
SheetViews sheetViews = new SheetViews();
SheetView sheetView = new SheetView()
{
TabSelected = false,
WorkbookViewId = (UInt32Value)0U
};
Pane pane = new Pane()
{
VerticalSplit = 7D,
TopLeftCell = freezeRangeFrom,
ActivePane = PaneValues.BottomLeft,
State = PaneStateValues.Frozen
};
sheetView.Append(pane);
sheetViews.Append(sheetView);
worksheet.Append(sheetViews);
worksheet.Append(sheetData);
wsp.Worksheet = worksheet;
wsp.Worksheet.Save();
#endregion
}
spreadsheetDocument.WorkbookPart.Workbook = wb;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
}
return true;
}
I need please. Please Help me....
This has bit me in the past. You have to add the view to the sheet before the data. You can try something like this:
public bool ExportData(DataSet ds, string destination, List<Tuple<string, string>> parms)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(destination, SpreadsheetDocumentType.Workbook))
{
WorkbookPart wbp = spreadsheetDocument.AddWorkbookPart();
WorksheetPart wsp = wbp.AddNewPart<WorksheetPart>();
Workbook wb = new Workbook();
FileVersion fv = new FileVersion();
fv.ApplicationName = "Microsoft Office Excel";
#region Freeze Panel
var freezeRow = parms.Count;
string freezeRangeFrom = $"A{freezeRow + 2}";
SheetViews sheetViews = new SheetViews();
SheetView sheetView = new SheetView()
{
TabSelected = false,
WorkbookViewId = (UInt32Value)0U
};
Pane pane = new Pane()
{
VerticalSplit = 7D,
TopLeftCell = freezeRangeFrom,
ActivePane = PaneValues.BottomLeft,
State = PaneStateValues.Frozen
};
sheetView.Append(pane);
#endregion
Worksheet worksheet = new Worksheet(new SheetViews(sheetView));
SheetData sheetData = new SheetData();
foreach (DataTable table in ds.Tables)
{
Row headerRow = new Row();
foreach (var parm in parms)
{
Row newRow = new Row();
// Write the parameter names
Cell parmNameCell = new Cell();
parmNameCell.DataType = CellValues.String;
parmNameCell.CellValue = new CellValue(parm.Item1.ToString()); //
parmNameCell.StyleIndex = 1;
newRow.AppendChild(parmNameCell);
// Write the parameter values
Cell parmValCell = new Cell();
parmValCell.DataType = CellValues.InlineString;
parmValCell.DataType = CellValues.String;
parmValCell.CellValue = new CellValue(parm.Item2?.ToString()); //
newRow.AppendChild(parmValCell);
sheetData.AppendChild(newRow);
}
Columns columns = new Columns();
int i = 1;
foreach (DataColumn column in table.Columns)
{
Column column1 = new Column();
column1.Min = Convert.ToUInt32(i);
column1.Max = Convert.ToUInt32(i);
column1.Width = insertSpaceBeforeUpperCAse(column.ColumnName).Length + 2;
column1.BestFit = true;
columns.Append(column1);
i++;
}
worksheet.Append(columns);
Row blankRow = new Row();
sheetData.AppendChild(blankRow);
//// Write the column names
List<string> columns2 = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns2.Add(column.ColumnName);
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(insertSpaceBeforeUpperCAse(column.ColumnName));
cell.StyleIndex = 1;
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
Row newRow = new Row();
foreach (string col in columns2)
{
Cell cell = new Cell();
cell.DataType = CellValues.String;
cell.CellValue = new CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
//worksheet.Append(sheetData);
//wsp.Worksheet = worksheet;
//wsp.Worksheet.Save();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = table.TableName;
sheet.SheetId = 1;
sheet.Id = wbp.GetIdOfPart(wsp);
sheets.Append(sheet);
wb.Append(fv);
wb.Append(sheets);
}
spreadsheetDocument.WorkbookPart.Workbook = wb;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
}
return true;
}
In case your SheetView does not work, I included an example of one that worked for me:
SheetView sheetView = new SheetView() { TabSelected = true, WorkbookViewId = (UInt32Value)0U };
Pane pane = new Pane() { VerticalSplit = 1D, TopLeftCell = "A2", ActivePane = PaneValues.BottomLeft, State = PaneStateValues.Frozen };
Selection selection = new Selection() { Pane = PaneValues.BottomLeft, ActiveCell = "A2", SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A2:XFD2" } };
sheetView.Append(pane);
sheetView.Append(selection);
Here is an example of how to freeze the first column.
var sheetViews = new SheetViews();
var sheetView = new SheetView() { TabSelected = true, WorkbookViewId = (UInt32Value)0U };
var pane = new Pane() { ActivePane = PaneValues.TopRight, HorizontalSplit = 1D, State = PaneStateValues.Frozen, TopLeftCell = "B1" };
var selection = new Selection() { Pane = PaneValues.TopRight };
sheetView.Append(pane);
sheetView.Append(selection);
sheetViews.Append(sheetView);
What I want to achieve is illustrated below:
The result and issue I've been having are illustrated below:
This is the result file my code has generated and there supposed to have expected content.
Window prompt after the 'Yes' button has clicked.
My running code is given below:
Main method:
public static void Main(string[] args)
{
WriteExcelService writeExcelService = new WriteExcelService();
Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>>
{
{ "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) },
{ "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) }
};
string inputFile = #"C:\{username}\Desktop\Valentines_Day.xlsx";
string sheetName = "Copy";
writeExcelService.WriteValueToCell(inputFile, sheetName, contentList);
}
WriteValueToCell method:
char columnName = 'I';
uint rowNumber = 1;
foreach (var keys in contentList.Keys)
{
foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value))
{
string cellAddress = String.Concat(columnName, rowNumber);
this.Write(filepath, sheetName, value, cellAddress, rowNumber);
int tempColumn = (int)columnName;
columnName = (char)++tempColumn;
}
columnName = 'I';
++rowNumber;
}
Write method:
private void Write(string filepath, string sheetName, string value, string cellAddress,uint rowNumber)
{
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook))
{
//writeExcelService.WriteValueToCell(outputFilePath, sheetName, cellAddress, value.Value);
// 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>();
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 = sheetName };
sheets.Append(sheet);
// Get the sheetData cell table.
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
// Add a row to the cell table.
Row row;
row = new Row() { RowIndex = rowNumber };
sheetData.Append(row);
// In the new row, find the column location to insert a cell.
Cell refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0)
{
refCell = cell;
break;
}
}
// Add the cell to the cell table.
Cell newCell = new Cell() { CellReference = cellAddress };
row.InsertBefore(newCell, refCell);
// Set the cell value to be a numeric value.
newCell.CellValue = new CellValue(value);
newCell.DataType = new EnumValue<CellValues>(CellValues.Number);
}
}
My problem is:
My code executes but once the result file is opened, It prompts window as I posted above, and the file is empty.If I debug the code to insert list of contents one by one, it can be written correctly to Cells I2 or J2. Since my code creates SpreadsheetDocument for each list content, therefore I have changed the SpreadsheetDocument creation approach in the code below:
using (SpreadsheetDocument spreadsheetDocument = File.Exists(filePath) ?
SpreadsheetDocument.Open(filepath, true) :
SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook))
{
}
But I am getting exception
Only one instance of the type is allowed for this parent.
Anyone can help me on this?
Appreciate it in advance.
Strings in excel are saved under a sharedStringTable. When inserting a string it is important to add the string or reference the string from the sharedStringTable. Also, you need to provide the correct DataType for a cell. In your code, you are inserting all values as a number:
// Set the cell value to be a numeric value.
newCell.CellValue = new CellValue(value);
newCell.DataType = new EnumValue<CellValues>(CellValues.Number);
To insert a string I would recommend using the following method after you have created a new cell:
private SpreadsheetDocument _spreadSheet;
private WorksheetPart _worksheetPart;
..
..
private void UpdateCell(Cell cell, DataTypes type, string text)
{
if (type == DataTypes.String)
{
cell.DataType = CellValues.SharedString;
if (!_spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Any())
{
_spreadSheet.WorkbookPart.AddNewPart<SharedStringTablePart>();
}
var sharedStringTablePart = _spreadSheet.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
if (sharedStringTablePart.SharedStringTable == null)
{
sharedStringTablePart.SharedStringTable = new SharedStringTable();
}
//Iterate through shared string table to check if the value is already present.
foreach (SharedStringItem ssItem in sharedStringTablePart.SharedStringTable.Elements<SharedStringItem>())
{
if (ssItem.InnerText == text)
{
cell.CellValue = new CellValue(ssItem.ElementsBefore().Count().ToString());
return;
}
}
// The text does not exist in the part. Create the SharedStringItem.
var item = sharedStringTablePart.SharedStringTable.AppendChild(new SharedStringItem(new Text(text)));
cell.CellValue = new CellValue(item.ElementsBefore().Count().ToString());
}
else if (type == DataTypes.Number)
{
cell.CellValue = new CellValue(text);
cell.DataType = CellValues.Number;
}
else if (type == DataTypes.DateTime)
{
cell.DataType = CellValues.Number;
cell.StyleIndex = Convert.ToUInt32(_dateStyleIndex);
DateTime dateTime = DateTime.Parse(text);
double oaValue = dateTime.ToOADate();
cell.CellValue = new CellValue(oaValue.ToString(CultureInfo.InvariantCulture));
}
_worksheetPart.Worksheet.Save();
}
I have figured out the solution myself. I have passed the list of string contents and write them all to corresponding Cells then closed the SpreadSheetDocument. In this way SpreadSheetDocument can be created once. Working code is below:
public void WriteValueToCell(string filepath, string sheetName, Dictionary<string, List<string>> contentList)
{
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook, true))
{
// Add a WorkbookPart to the document.
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
//Add a WorkbookStylesPart to the workbookpart
WorkbookStylesPart stylesPart = workbookpart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = new Stylesheet();
// Add a WorksheetPart to the WorkbookPart.
WorksheetPart worksheetPart = 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 = sheetName };
sheets.Append(sheet);
// Get the sheetData cell table.
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
char columnName = 'I';
uint rowNumber = 1;
foreach (var keys in contentList.Keys)
{
foreach (var value in contentList.Where(v => v.Key == keys).SelectMany(v => v.Value))
{
string cellAddress = String.Concat(columnName, rowNumber);
// Add a row to the cell table.
Row row;
row = new Row() { RowIndex = rowNumber };
sheetData.Append(row);
// In the new row, find the column location to insert a cell.
Cell refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (string.Compare(cell.CellReference.Value, cellAddress, true) > 0)
{
refCell = cell;
break;
}
}
// Add the cell to the cell table.
Cell newCell = new Cell() { CellReference = cellAddress };
row.InsertBefore(newCell, refCell);
// Set the cell value to be a numeric value.
newCell.CellValue = new CellValue(value);
newCell.DataType = new EnumValue<CellValues>(CellValues.String);
int tempColumn = (int)columnName;
columnName = (char)++tempColumn;
}
columnName = 'I';
++rowNumber;
}
}
}
Main method:
public static void Main(string[] args)
{
WriteExcelService writeExcelService = new WriteExcelService();
Dictionary<string, List<string>> contentList = new Dictionary<string, List<string>>
{
{ "en-US",new List<string> (new string[] { "Dummy text 01","Dummy text 02"}) },
{ "es-ES",new List<string> (new string[] { "Texto ficticio 01", "Texto ficticio 02"}) }
};
string inputFile = #"C:\{username}\Desktop\Valentines_Day.xlsx";
string sheetName = "Copy";
writeExcelService.WriteValueToCell(inputFile, sheetName, contentList);
}
How can we able to write next row of the excel sheet if it ave records during exporting data from c#
it is the code i used for exporting data. to excel . i failed to export the data to next line by this code
private void ExportToOxml(bool firstTime)
{
if (count == 0)
{
ResultsData.Columns.Remove("TotalRecords");
ResultsData.Columns.Remove("PageIndex");
// fileName = #"C:\MyExcel.csv";
//Delete the file if it exists.
if (firstTime && File.Exists(xsfd.FileName))
{
File.Delete(fileName);
}
count++;
}
if (firstTime)
{
//This is the first time of creating the excel file and the first sheet.
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.
Create(fileName, SpreadsheetDocumentType.Workbook);
// Add a WorkbookPart to the document.
WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// Add a WorksheetPart to the WorkbookPart.
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
var bold1 = new System.Windows.Documents.Bold();
CellFormat cf = new CellFormat();
// Add Sheets to the Workbook.
Sheets sheets;
sheets = spreadsheetDocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new 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();
foreach (DataColumn column in ResultsData.Columns)
{
var cell = new Cell { DataType = CellValues.String, CellValue = new CellValue(column.ColumnName) };
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow row in ResultsData.Rows)
{
var newRow = new Row();
foreach (DataColumn col in ResultsData.Columns)
{
var cell = new Cell
{
DataType = CellValues.String,
CellValue = new CellValue(row[col].ToString())
};
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
workbookpart.Workbook.Save();
spreadsheetDocument.Close();
}
else
{
// Open the Excel file that we created before, and start to add sheets to it.
var spreadsheetDocument = SpreadsheetDocument.Open(fileName, true);
var workbookpart = spreadsheetDocument.WorkbookPart;
if (workbookpart.Workbook == null)
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
var sheets = spreadsheetDocument.WorkbookPart.Workbook.Sheets;
if (sheets.Elements<Sheet>().Any())
{
//Set the new sheet id
sheetId = sheets.Elements<Sheet>().Max(s => s.SheetId.Value) + 1;
}
else
{
sheetId = 1;
}
// 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 the header row here.
var headerRow = new Row();
foreach (DataColumn column in ResultsData.Columns)
{
var cell = new Cell { DataType = CellValues.String, CellValue = new CellValue(column.ColumnName) };
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow row in ResultsData.Rows)
{
var newRow = new Row();
foreach (DataColumn col in ResultsData.Columns)
{
var cell = new Cell
{
DataType = CellValues.String,
CellValue = new CellValue(row[col].ToString())
};
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
workbookpart.Workbook.Save();
// Close the document.
spreadsheetDocument.Close();
}
}