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
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
}
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);
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);
I am reading XML data then I pasted to data-set and the I created spreadsheet and copied the data to to sheets in spreadsheet.So now I want to only allow some sheets and cells to read-only. To prevent to no changes to headers and data in some sheets, So I am posting code used to convert the XML to excel using open XML. So I need to prevent write for some sheets and also cells some sheets.
public void ExportDSToExcel(DataSet ds, string dest)
{
using (var workbook = SpreadsheetDocument.Create(dest, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();
uint sheetId = 1;
foreach (DataTable table in ds.Tables)
{
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);
DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
{
sheetId =
sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = table.TableName };
sheets.Append(sheet);
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
foreach (DataColumn column in table.Columns)
{
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in table.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if(txtname.Text != null)
{
if (FileUpload1.HasFile == true)
{
string myXMLfile = "/uploads/" + FileUpload1.FileName;
FileUpload1.SaveAs(Server.MapPath(myXMLfile));
string dest = "D:/uploads/" + txtname.Text+".xlsx";
DataSet ds = new DataSet();
try
{
ds.ReadXml(myXMLfile);
}
catch (Exception ex)
{
lblstatus.Text=(ex.ToString());
}
ExportDSToExcel(ds, dest);
}
else
{
lblstatus.Text = "Please Upload the file ";
}
}
else {
lblstatus.Text = "Please enter the name ";
}
}
}
thanks in advance so please help me to find solution in this code.
We can customise protection by password in different means.For making excel sheet specified area or column or row as read only or a full sheet into read only by giving protection to sheet by password.If we want to protect whole sheet use this code
PageMargins pageM = sheetPart.Worksheet.GetFirstChild<PageMargins>();
SheetProtection sheetProtection = new SheetProtection();
sheetProtection.Password = "admin";
sheetProtection.Sheet = true;
sheetProtection.Objects = true;
sheetProtection.Scenarios = true;
ProtectedRanges pRanges = new ProtectedRanges();
ProtectedRange pRange = new ProtectedRange();
ListValue<StringValue> lValue = new ListValue<StringValue>();
lValue.InnerText = ""; //set cell which you want to make it editable
pRange.SequenceOfReferences = lValue;
pRange.Name = "not allow editing";
pRanges.Append(pRange);
sheetPart.Worksheet.InsertBefore(sheetProtection, pageM);
sheetPart.Worksheet.InsertBefore(pRanges, pageM);
If we want specified page as read only then first give a condition filter by name then give this code .In this code lValue.InnerText = ""; is null so we are not mention cells have permission to overcome this protection. If we mention the cells we can edit up to that limit.
I narrowed it down to:
//aantal auto's
Row aantalAutosRow = new Row();
aantalAutosRow.RowIndex = Convert.ToUInt32((tblXML.Rows.Count) + 2);
Cell aantalAutosCell = new Cell();
aantalAutosCell.CellReference = getColumnName(1);
aantalAutosCell.CellValue = new CellValue("Hoi");
aantalAutosRow.Append(aantalAutosCell);
sheetData.Append(aantalAutosRow);
This generates the Cell after I click yes when Excel prompts to fix the file (sheet.xml)
Complete class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO;
using System.Xml;
using System.Data;
namespace XML_naar_Excel
{
class Excel
{
public void convertToExcel(string padXml)
{
//maak dataset en vul met ingevoerde xml
DataSet dsXML = new DataSet();
dsXML.ReadXml(padXml);
DataTable tblXML = dsXML.Tables[2];
//opslaan
string padXlsx = Path.GetDirectoryName(padXml) + "\\voorraad " + DateTime.Now.Day + "-" + DateTime.Now.Month + "-" + DateTime.Now.Year + ".xlsx";
//spreadsheet
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(padXlsx, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Workbook workbook = new Workbook();
FileVersion fv = new FileVersion();
fv.ApplicationName = "Microsoft Office Excel";
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
//styles
Style s = new Style();
WorkbookStylesPart stylesPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = s.GenerateStyleSheet();
stylesPart.Stylesheet.Save();
//kolommen
Columns columns = new Columns();
for (int i = 1; i < tblXML.Columns.Count; i++)
{
Column column = new Column();
column.Min = Convert.ToUInt32(i);
column.Max = Convert.ToUInt32(i + 1);
int lengte = tblXML.Rows[13][i-1].ToString().Length;
if (lengte < 10)
{
lengte = 10;
}
else if (lengte > 35)
{
lengte = 35;
}
else
{
lengte += 5;
}
column.Width = lengte;
column.BestFit = true;
columns.Append(column);
}
worksheet.Append(columns);
//header
Row header = new Row();
header.RowIndex = (UInt32)1;
foreach (DataColumn columnInDataTable in tblXML.Columns)
{
Cell headerCell = createTextCell(tblXML.Columns.IndexOf(columnInDataTable) + 1, 1, columnInDataTable.ColumnName);
headerCell.StyleIndex = 1;
header.AppendChild(headerCell);
}
sheetData.AppendChild(header);
// Add a row to the cell table.
for (int i = 1; i < tblXML.Rows.Count; i++)
{
Row row;
row = new Row() { RowIndex = Convert.ToUInt32(i) + 1 };
for (int j = 0; j < tblXML.Columns.Count; j++)
{
Cell newCell = new Cell()
{
CellReference = getColumnName(i),
DataType = CellValues.String,
StyleIndex = 6,
CellValue = new CellValue(tblXML.Rows[i][j].ToString()),
};
row.Append(newCell);
}
sheetData.Append(row);
}
//autofilter
string laatsteKolom = zoekLaatsteKolom(tblXML);
AutoFilter autoFilter = new AutoFilter();
autoFilter.Reference = "A1:" + laatsteKolom + "1";
//aantal auto's
Row aantalAutosRow = new Row();
aantalAutosRow.RowIndex = Convert.ToUInt32((tblXML.Rows.Count) + 2);
Cell aantalAutosCell = new Cell();
aantalAutosCell.CellReference = getColumnName(1);
aantalAutosCell.CellValue = new CellValue("Hoi");
//CellFormula berekenAantalAutos = new CellFormula();
//berekenAantalAutos.Text = "=COUNTA(A2:A" + tblXML.Rows.Count.ToString();
//aantalAutosCell.Append(berekenAantalAutos);
aantalAutosRow.Append(aantalAutosCell);
sheetData.Append(aantalAutosRow);
worksheet.Append(sheetData);
worksheet.Append(autoFilter);
worksheetPart.Worksheet = worksheet;
worksheetPart.Worksheet.Save();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = "Voorraad";
sheet.SheetId = 1;
sheet.Id = workbookPart.GetIdOfPart(worksheetPart);
sheets.Append(sheet);
workbook.Append(fv);
workbook.Append(sheets);
spreadsheetDocument.WorkbookPart.Workbook = workbook;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
}
}
//kolom naam (letter) ophalen
private string getColumnName(int columnIndex)
{
int dividend = columnIndex;
string columnName = String.Empty;
int modifier;
while (dividend > 0)
{
modifier = (dividend - 1) % 26;
columnName =
Convert.ToChar(65 + modifier).ToString() + columnName;
dividend = (int)((dividend - modifier) / 26);
}
return columnName;
}
private Cell createTextCell(int columnIndex, int rowIndex, object cellValue)
{
Cell cell = new Cell();
cell.DataType = CellValues.InlineString;
cell.CellReference = getColumnName(columnIndex) + rowIndex;
InlineString inlineString = new InlineString();
Text t = new Text();
t.Text = cellValue.ToString();
inlineString.AppendChild(t);
cell.AppendChild(inlineString);
return cell;
}
string zoekLaatsteKolom(DataTable tblXML)
{
string kolom;
kolom = getColumnName(tblXML.Columns.Count);
return kolom;
}
}
}
Can someone tell me what I'm doing that is illegal to Excel? I think excel makes SharedStrings when mending it. I never worked with SharedStrings and I hope I don't have to.
I went through your code and found 4 places that needed change in order to generate a fault-free excel document.
1. Replaced stylesPart.Stylesheet = s.GenerateStyleSheet();
by stylesPart.Stylesheet = new Stylesheet();
2. Commented out the following : //headerCell.StyleIndex = 1;
3. Commented out the following : //StyleIndex = 6,
4. Added the following : aantalAutosCell.DataType = CellValues.String;
The code posted below works for me and generates an error free excel document.
Few pointers you need to know
1. You cannot arbitrarily assign style indices when working with Open XML Docs
2. When ever you have a string data type to be stored you should use CellValues.String (since you don't want to use Shared String)
3. It's really worth while to read about SharedStrings when working with Open XML SDK. Shared Strings reduce the overall size of your file and make things so much better. See http://msdn.microsoft.com/en-us/library/office/gg278314.aspx
using System;
using System.Data;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
namespace TestOpenXmlSDK
{
class Excel
{
public void convertToExcel(string padXml)
{
//maak dataset en vul met ingevoerde xml
DataSet dsXML = new DataSet();
dsXML.ReadXml(padXml);
DataTable tblXML = dsXML.Tables[2];
//opslaan
string padXlsx = Path.GetDirectoryName(padXml) + DateTime.Now.Day + "-" + DateTime.Now.Month + "-" + DateTime.Now.Year + ".xlsx";
//spreadsheet
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(padXlsx, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Workbook workbook = new Workbook();
FileVersion fv = new FileVersion();
fv.ApplicationName = "Microsoft Office Excel";
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
//styles
WorkbookStylesPart stylesPart = spreadsheetDocument.WorkbookPart.AddNewPart<WorkbookStylesPart>();
stylesPart.Stylesheet = new Stylesheet();
stylesPart.Stylesheet.Save();
//kolommen
DocumentFormat.OpenXml.Spreadsheet.Columns columns = new Columns();
for (int i = 1; i < tblXML.Columns.Count; i++)
{
Column column = new Column();
column.Min = Convert.ToUInt32(i);
column.Max = Convert.ToUInt32(i + 1);
int lengte = tblXML.Rows[13][i - 1].ToString().Length;
if (lengte < 10)
{
lengte = 10;
}
else if (lengte > 35)
{
lengte = 35;
}
else
{
lengte += 5;
}
column.Width = lengte;
column.BestFit = true;
columns.Append(column);
}
worksheet.Append(columns);
//header
Row header = new Row();
header.RowIndex = (UInt32)1;
foreach (DataColumn columnInDataTable in tblXML.Columns)
{
Cell headerCell = createTextCell(tblXML.Columns.IndexOf(columnInDataTable) + 1, 1, columnInDataTable.ColumnName);
//headerCell.StyleIndex = 1;
header.AppendChild(headerCell);
}
sheetData.AppendChild(header);
// Add a row to the cell table.
for (int i = 1; i < tblXML.Rows.Count; i++)
{
Row row;
row = new Row() { RowIndex = Convert.ToUInt32(i) + 1 };
for (int j = 0; j < tblXML.Columns.Count; j++)
{
Cell newCell = new Cell()
{
CellReference = getColumnName(i),
DataType = CellValues.Number,
//StyleIndex = 6,
CellValue = new CellValue(tblXML.Rows[i][j].ToString()),
};
row.Append(newCell);
}
sheetData.Append(row);
}
//autofilter
string laatsteKolom = zoekLaatsteKolom(tblXML);
AutoFilter autoFilter = new AutoFilter();
autoFilter.Reference = "A1:" + laatsteKolom + "1";
//aantal auto's
Row aantalAutosRow = new Row();
aantalAutosRow.RowIndex = Convert.ToUInt32((tblXML.Rows.Count) + 2);
Cell aantalAutosCell = new Cell();
aantalAutosCell.CellReference = getColumnName(1);
aantalAutosCell.CellValue = new CellValue("Hoi");
aantalAutosCell.DataType = CellValues.String;
//CellFormula berekenAantalAutos = new CellFormula();
//berekenAantalAutos.Text = "=COUNTA(A2:A" + tblXML.Rows.Count.ToString();
//aantalAutosCell.Append(berekenAantalAutos);
aantalAutosRow.Append(aantalAutosCell);
sheetData.Append(aantalAutosRow);
worksheet.Append(sheetData);
worksheet.Append(autoFilter);
worksheetPart.Worksheet = worksheet;
worksheetPart.Worksheet.Save();
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = "Voorraad";
sheet.SheetId = 1;
sheet.Id = workbookPart.GetIdOfPart(worksheetPart);
sheets.Append(sheet);
workbook.Append(fv);
workbook.Append(sheets);
spreadsheetDocument.WorkbookPart.Workbook = workbook;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
}
}
//kolom naam (letter) ophalen
private string getColumnName(int columnIndex)
{
int dividend = columnIndex;
string columnName = String.Empty;
int modifier;
while (dividend > 0)
{
modifier = (dividend - 1) % 26;
columnName =
Convert.ToChar(65 + modifier).ToString() + columnName;
dividend = (int)((dividend - modifier) / 26);
}
return columnName;
}
private Cell createTextCell(int columnIndex, int rowIndex, object cellValue)
{
Cell cell = new Cell();
cell.DataType = CellValues.InlineString;
cell.CellReference = getColumnName(columnIndex) + rowIndex;
InlineString inlineString = new InlineString();
Text t = new Text();
t.Text = cellValue.ToString();
inlineString.AppendChild(t);
cell.AppendChild(inlineString);
return cell;
}
string zoekLaatsteKolom(DataTable tblXML)
{
string kolom;
kolom = getColumnName(tblXML.Columns.Count);
return kolom;
}
}
}