I'm using NPOI to manipulate Excel(.xlsx) file data & format. I was wondering if there is a way to format the cell range to the table.
// something like.
ITable table = worksheet.FormatAsTable("A1:C4");
Have done some research on the internet but no luck yet. Any help would be much appreciated!
[2021/05/28 Update]:
Thanks for reminding. Found that without setting ctTable's id, name and displayName would get this error Removed Part: /xl/tables/table1.xml part with XML error. (Table) Load error. Line 1, column 247. (Following sample code fixed.)
Based on comment and link offered by #Gian Paolo, the C# way to achieve 'format as table' with NPOI would be like this:
Install-Package NPOI -Version 2.5.3
// NPOI dependencies
using NPOI.OpenXmlFormats.Spreadsheet;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
IWorkbook workbook = new XSSFWorkbook();
XSSFSheet worksheet = workbook.CreateSheet("Grades") as XSSFSheet;
InsertTestData(worksheet);
// Format Cell Range As Table
XSSFTable xssfTable = worksheet.CreateTable();
CT_Table ctTable = xssfTable.GetCTTable();
AreaReference myDataRange = new AreaReference(new CellReference(0, 0), new CellReference(3, 2));
ctTable.#ref = myDataRange.FormatAsString();
ctTable.id = 1;
ctTable.name = "Table1";
ctTable.displayName = "Table1";
ctTable.tableStyleInfo = new CT_TableStyleInfo();
ctTable.tableStyleInfo.name = "TableStyleMedium2"; // TableStyleMedium2 is one of XSSFBuiltinTableStyle
ctTable.tableStyleInfo.showRowStripes = true;
ctTable.tableColumns = new CT_TableColumns();
ctTable.tableColumns.tableColumn = new List<CT_TableColumn>();
ctTable.tableColumns.tableColumn.Add(new CT_TableColumn() { id = 1, name = "ID" });
ctTable.tableColumns.tableColumn.Add(new CT_TableColumn() { id = 2, name = "Name" });
ctTable.tableColumns.tableColumn.Add(new CT_TableColumn() { id = 3, name = "Score" });
using (FileStream file = new FileStream(#"test.xlsx", FileMode.Create))
{
workbook.Write(file);
}
// Function to Populate Test Data
private void InsertTestData(XSSFSheet worksheet)
{
worksheet.CreateRow(0);
worksheet.GetRow(0).CreateCell(0).SetCellValue("ID");
worksheet.GetRow(0).CreateCell(1).SetCellValue("Name");
worksheet.GetRow(0).CreateCell(2).SetCellValue("Score");
worksheet.CreateRow(1);
worksheet.GetRow(1).CreateCell(0).SetCellValue(1);
worksheet.GetRow(1).CreateCell(1).SetCellValue("John");
worksheet.GetRow(1).CreateCell(2).SetCellValue(82);
worksheet.CreateRow(2);
worksheet.GetRow(2).CreateCell(0).SetCellValue(2);
worksheet.GetRow(2).CreateCell(1).SetCellValue("Sam");
worksheet.GetRow(2).CreateCell(2).SetCellValue(90);
worksheet.CreateRow(3);
worksheet.GetRow(3).CreateCell(0).SetCellValue(3);
worksheet.GetRow(3).CreateCell(1).SetCellValue("Amy");
worksheet.GetRow(3).CreateCell(2).SetCellValue(88);
}
Result:
Not enough rep to add a comment - but if anyone is getting strange Excel errors when everything looks fine, I had an issue with iterating an object list into tableColumn. Building an array first fixed all my issues:
var headerNames = _headers.Select(x => x.Name).ToArray();
for (uint i = 0; i < headerNames.Count; i++)
{
ctTable.tableColumns.tableColumn.Add(new CT_TableColumn() { id = i + 1, name = headerNames[i] });
}
Related
I'm using ClosedXML elsewhere in my script where I'm iterating through every row like this and it works.
var workbook = new XLWorkbook(ObjectRepPath);
var rows = workbook.Worksheet(1).RangeUsed().RowsUsed().Skip(1);
foreach (var row in rows)
{
objPage = row.Cell(1).GetString();
objElement = row.Cell(2).GetString();
if (objPage == page && objElement == element)
{
locType = row.Cell(3).GetString();
locParm = row.Cell(4).GetString();
}
}
After that I need to pull the data from the cells in a randomly selected row. Here's what I've got so far, which is not working...
var workbook = new XLWorkbook(extFile);
var ws = workbook.Worksheets.Add("Cell Values");
var rnd = new Random();
int rowNum = rnd.Next(2, workbook.Worksheet(1).RangeUsed().RowsUsed().Count());
var dataRow = ws.Row(rowNum);
string dangit = dataRow.Cell(1).GetString();
System.Diagnostics.Debug.WriteLine("Why is this dang thing not working... " + dangit);
Output: Why is this damn thing not working...
It just comes back empty. No error. Does anyone see something I don't?
Alright, I found the solution.
I changed the line ...
var ws = workbook.Worksheets.Add("Cell Values");
to ....
var ws = workbook.Worksheet(1);
and now this works ....
Storage.StreetAddress = ws.Cell(xlRow, 1).GetString();
I am trying to create a drop list, haven't had any luck finding similar sample code or documentation to follow so I'm flying solo
When I run this sample code I created
static void Main(string[] args)
{
using (FileStream filename = new FileStream(#"INSERTYOUROWNPATH.xlsx", FileMode.Create))
{
var workbook = new XSSFWorkbook();
XSSFSheet xsheet = (XSSFSheet)workbook.CreateSheet("Validation");
CT_DataValidation valid = new CT_DataValidation();
valid.showDropDown = true;
valid.allowBlank = true;
var constraint = new XSSFDataValidationConstraint(new string[] { "0064", "0061" }); //to be used in list
var range = new CellRangeAddressList(11, 14, 13, 13); //apply to row 12:14 starting at column N finishing at column N
var addingconstraint = new XSSFDataValidation(constraint, range, valid);
addingconstraint.EmptyCellAllowed = true;
addingconstraint.SuppressDropDownArrow = false;
xsheet.AddValidationData(addingconstraint);
workbook.Write(filename);
}
}
I get the following errors when I open the spreadsheet:
"We found a problem with some content in "Validations.xlsx" do you
want use to try to recover as much as we can? If you trust the source
of this workbook, click Yes"
Then I get the following repair message:
"Repaired Part: /xl/worksheets/sheet1.xml part with XML error. Load
error. Line 1 column 684"
Could I please get some insight in to where this is failing?
your issue seems to be very similar to this problem about data validation and data constraint.
XSSFDataValidation dataValidation = null;
XSSFDataValidationConstraint dvConstraint = null;
XSSFDataValidationHelper validationHelper = null;
int DVRowLimit = (Int16.MaxValue);
XSSFCellStyle numberCellStyle = (XSSFCellStyle)workbook.CreateCellStyle();
XSSFDataFormat numberDataFormat = (XSSFDataFormat)workbook.CreateDataFormat();
numberCellStyle.SetDataFormat(numberDataFormat.GetFormat("#,###,###"));
CellRangeAddressList cellRangeFieldsType1 = new CellRangeAddressList(1, DVRowLimit, headerCount, headerCount);
dvConstraint = (XSSFDataValidationConstraint)validationHelper.CreateintConstraint(OperatorType.BETWEEN, "0", Int64.MaxValue.ToString());
dataValidation = (XSSFDataValidation)validationHelper.CreateValidation(dvConstraint, cellRangeFieldsType1);
dataValidation.ShowErrorBox = true;
dataValidation.SuppressDropDownArrow = true;
dataValidation.ErrorStyle = 0;
dataValidation.CreateErrorBox("InvalidValue", "Number Should be a integer.");
dataValidation.ShowErrorBox = true;
dataValidation.CreatePromptBox("Number Data Validation", "Enter Number.");
dataValidation.ShowPromptBox = true;
sheet.AddValidationData(dataValidation);
sheet.SetDefaultColumnStyle(column, numberCellStyle);
I am trying to export some data to an excel sheet S1 whose data would be shown as Pivoted views in the next two sheets S2 and S3. I am able to create a single pivot and it works perfect. But when I create two pivots, the consequent Excel file renders as corrupt.
By corrupt I mean,
On clicking yes, I get this -
Here is the code I am using to create the pivots -
using XL = ClosedXML.Excel;
...
XL.XLWorkbook wb = new XL.XLWorkbook();
dsData = Session["ExportData"] as DataSet;
var sheet1 = wb.Worksheets.Add("output table");
sheet1.Cell(1, 1).InsertTable(dsData.Tables[0], "output table", true);
// sheet1 is the reference sheet S1
var dataRange = sheet1.RangeUsed();
// First Pivot
XL.IXLWorksheet ptSheet1 = wb.Worksheets.Add("S2");
var pt1 = ptSheet1.PivotTables.AddNew("PivotTable1", ptSheet.Cell(3, 1), dataRange);
pt1.ReportFilters.Add("CX");
pt1.RowLabels.Add("C1");
pt1.RowLabels.Add("C2");
pt1.RowLabels.Add("C3");
pt1.RowLabels.Add("C4");
pt1.ColumnLabels.Add("CL1");
pt1.ColumnLabels.Add("CL2");
pt1.ColumnLabels.Add("CL3");
pt1.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum;
// Second Pivot
XL.IXLWorksheet ptSheet2 = wb.Worksheets.Add("S3");
var pt2 = ptSheet2.PivotTables.AddNew("PivotTable2", ptSheet1.Cell(3, 1), dataRange);
pt2.ReportFilters.Add("QQ");
pt2.RowLabels.Add("C1");
pt2.RowLabels.Add("C2");
pt2.ColumnLabels.Add("CL1");
pt2.ColumnLabels.Add("CL2");
pt2.ColumnLabels.Add("CL3");
pt2.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum;
C1, C2, C3. C4 and V are the column names in my reference sheet S1.
The issue is caused by a ClosedXML implementation bug.
It can easily be reproduced by using the following snippet (a modified version of their Pivot Tables example) and opening the resulting file in Excel:
static void CreateTestPivotTables(string filePath)
{
var wb = new XLWorkbook();
var wsData = wb.Worksheets.Add("Data");
wsData.Cell("A1").Value = "Category";
wsData.Cell("A2").Value = "A";
wsData.Cell("A3").Value = "B";
wsData.Cell("A4").Value = "B";
wsData.Cell("B1").Value = "Number";
wsData.Cell("B2").Value = 100;
wsData.Cell("B3").Value = 150;
wsData.Cell("B4").Value = 75;
var source = wsData.Range("A1:B4");
for (int i = 1; i <= 2; i++)
{
var name = "PT" + i;
var wsPT = wb.Worksheets.Add(name);
var pt = wsPT.PivotTables.AddNew(name, wsPT.Cell("A1"), source);
pt.RowLabels.Add("Category");
pt.Values.Add("Number")
.ShowAsPctFrom("Category").And("A")
.NumberFormat.Format = "0%";
}
wb.SaveAs(filePath);
}
The bug is located in XLWorkbook_Save.cs - GeneratePivotTables method:
private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart,
XLWorksheet xlWorksheet,
SaveContext context)
{
foreach (var pt in xlWorksheet.PivotTables)
{
var ptCdp = context.RelIdGenerator.GetNext(RelType.Workbook);
var pivotTableCacheDefinitionPart = workbookPart.AddNewPart<PivotTableCacheDefinitionPart>(ptCdp);
GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt);
var pivotCaches = new PivotCaches();
var pivotCache = new PivotCache {CacheId = 0U, Id = ptCdp};
pivotCaches.AppendChild(pivotCache);
workbookPart.Workbook.AppendChild(pivotCaches);
var pivotTablePart =
worksheetPart.AddNewPart<PivotTablePart>(context.RelIdGenerator.GetNext(RelType.Workbook));
GeneratePivotTablePartContent(pivotTablePart, pt);
pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook));
}
}
by the line workbookPart.Workbook.AppendChild(pivotCaches); which adds multiple PivotCaches to workbookPart.Workbook while it's allowed to contain 0 or 1.
With that being said, the only way to fix it is inside the source code by modifying the above method as follows:
private static void GeneratePivotTables(WorkbookPart workbookPart, WorksheetPart worksheetPart,
XLWorksheet xlWorksheet,
SaveContext context)
{
var pivotCaches = workbookPart.Workbook.GetFirstChild<PivotCaches>();
foreach (var pt in xlWorksheet.PivotTables)
{
var ptCdp = context.RelIdGenerator.GetNext(RelType.Workbook);
var pivotTableCacheDefinitionPart = workbookPart.AddNewPart<PivotTableCacheDefinitionPart>(ptCdp);
GeneratePivotTableCacheDefinitionPartContent(pivotTableCacheDefinitionPart, pt);
if (pivotCaches == null)
workbookPart.Workbook.AppendChild(pivotCaches = new PivotCaches());
var pivotCache = new PivotCache { CacheId = (uint)pivotCaches.Count(), Id = ptCdp };
pivotCaches.AppendChild(pivotCache);
var pivotTablePart =
worksheetPart.AddNewPart<PivotTablePart>(context.RelIdGenerator.GetNext(RelType.Workbook));
GeneratePivotTablePartContent(pivotTablePart, pt);
pivotTablePart.PivotTableDefinition.CacheId = pivotCache.CacheId;
pivotTablePart.AddPart(pivotTableCacheDefinitionPart, context.RelIdGenerator.GetNext(RelType.Workbook));
}
}
Update: The good news are that my post triggered a ClosedXML source repository fix by Francois Botha (also credits to petelids who brought it up there), so you can take the code from there until their next release which hopefully will include it.
Try this modification. I made a note where I added an additional line. Also, I think the AddNew() method may have had the wrong worksheet reference? You may have been trying to add a pivot table on top of another one. That may have been the real issue rather than the additional line I added.
using XL = ClosedXML.Excel;
...
XL.XLWorkbook wb = new XL.XLWorkbook();
dsData = Session["ExportData"] as DataSet;
var sheet1 = wb.Worksheets.Add("output table");
sheet1.Cell(1, 1).InsertTable(dsData.Tables[0], "output table", true);
// sheet1 is the reference sheet S1
var dataRange = sheet1.RangeUsed();
PivotCache cache = wb.PivotCaches.Add(dataRange); //---THIS LINE HAS BEEN ADDED---
// First Pivot
XL.IXLWorksheet ptSheet1 = wb.Worksheets.Add("S2");
var pt1 = ptSheet1.PivotTables.AddNew("PivotTable1", ptSheet1.Cell(3, 1), cache);
//Changed ptSheet.Cell... to ptSheet1.Cell...
pt1.ReportFilters.Add("CX");
pt1.RowLabels.Add("C1");
pt1.RowLabels.Add("C2");
pt1.RowLabels.Add("C3");
pt1.RowLabels.Add("C4");
pt1.ColumnLabels.Add("CL1");
pt1.ColumnLabels.Add("CL2");
pt1.ColumnLabels.Add("CL3");
pt1.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum;
// Second Pivot
XL.IXLWorksheet ptSheet2 = wb.Worksheets.Add("S3");
var pt2 = ptSheet2.PivotTables.AddNew("PivotTable2", ptSheet2.Cell(3, 1), cache);
//Changed ptSheet1.Cell... to ptSheet2.Cell...
pt2.ReportFilters.Add("QQ");
pt2.RowLabels.Add("C1");
pt2.RowLabels.Add("C2");
pt2.ColumnLabels.Add("CL1");
pt2.ColumnLabels.Add("CL2");
pt2.ColumnLabels.Add("CL3");
pt2.Values.Add("V").SummaryFormula = XL.XLPivotSummary.Sum;
I have an excel file which contains lots of data along with icon sets and data bars based on the values in the cell. It looks like this:
I want to import this excel sheet along with the conditional formatting. Is there any library for this?? I went through this http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt6 but it only imports data not format.
If that's not possible is there code in epplus to have these iconsets in excel sheet. I can have arrows, traffic lights, etc but not these.
I dont think EPP supports custom conditional formatting which are stored as "Workbook Extensions" in the xml of the Excel file. You could copy the xml node of the "extLst" which contains the custom formatting from one worksheet to another. Just make sure there is nothing else beside the cond formatting xml in the node that you do not want copied in which case you will have to select only the child nodes you want.
To test, i created the following excel sheet (temp.xlsx), did a copy.paste of values only and saved to a new file (temp2.xlsx):
Then ran the following and it successfully copied the formatting over:
public void Custom_Condition_Copy_Test()
{
//http://stackoverflow.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus
//File with custom conditional formatting
var existingFile = new FileInfo(#"c:\temp\temp.xlsx");
//Copy of the file with the conditonal formatting removed
var existingFile2 = new FileInfo(#"c:\temp\temp2.xlsx");
using (var package = new ExcelPackage(existingFile))
using (var package2 = new ExcelPackage(existingFile2))
{
//Make sure there are document element for the source
var worksheet = package.Workbook.Worksheets.First();
var xdoc = worksheet.WorksheetXml;
if (xdoc.DocumentElement == null)
return;
//Make sure there are document element for the destination
var worksheet2 = package2.Workbook.Worksheets.First();
var xdoc2 = worksheet2.WorksheetXml;
if (xdoc2.DocumentElement == null)
return;
//get the extension list node 'extLst' from the ws with the formatting
var extensionlistnode = xdoc
.DocumentElement
.GetElementsByTagName("extLst")[0];
//Create the import node and append it to the end of the xml document
var newnode = xdoc2.ImportNode(extensionlistnode, true);
xdoc2.LastChild.AppendChild(newnode);
package2.Save();
}
}
Might want to put some try's in there but this should get you close.
UPDATE: Based on OPs comment.
If you want to be able to add the custom conditional format without the need of the original file that contains it, I see two options.
Option 1, you do it the more "correct" way and use the DocumentFormat.OpenXml namespace. BUT, this would require you to have the Office Open XML library available which may or may not be so easy depending on the environment you are running this in. You can get it from here http://www.microsoft.com/en-us/download/details.aspx?id=30425 and it comes with a Reflection tool that can generate the code you want which gets you this:
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
using X14 = DocumentFormat.OpenXml.Office2010.Excel;
using Excel = DocumentFormat.OpenXml.Office.Excel;
......
WorksheetExtensionList worksheetExtensionList1 = new WorksheetExtensionList();
WorksheetExtension worksheetExtension1 = new WorksheetExtension(){ Uri = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}" };
worksheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
X14.ConditionalFormattings conditionalFormattings1 = new X14.ConditionalFormattings();
X14.ConditionalFormatting conditionalFormatting1 = new X14.ConditionalFormatting();
conditionalFormatting1.AddNamespaceDeclaration("xm", "http://schemas.microsoft.com/office/excel/2006/main");
X14.ConditionalFormattingRule conditionalFormattingRule1 = new X14.ConditionalFormattingRule(){ Type = ConditionalFormatValues.IconSet, Priority = 2, Id = "{CD6B2710-0474-449D-881A-22CFE15D011D}" };
X14.IconSet iconSet1 = new X14.IconSet(){ IconSetTypes = X14.IconSetTypeValues.FiveArrows, Custom = true };
X14.ConditionalFormattingValueObject conditionalFormattingValueObject1 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula1 = new Excel.Formula();
formula1.Text = "0";
conditionalFormattingValueObject1.Append(formula1);
X14.ConditionalFormattingValueObject conditionalFormattingValueObject2 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula2 = new Excel.Formula();
formula2.Text = "20";
conditionalFormattingValueObject2.Append(formula2);
X14.ConditionalFormattingValueObject conditionalFormattingValueObject3 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula3 = new Excel.Formula();
formula3.Text = "40";
conditionalFormattingValueObject3.Append(formula3);
X14.ConditionalFormattingValueObject conditionalFormattingValueObject4 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula4 = new Excel.Formula();
formula4.Text = "60";
conditionalFormattingValueObject4.Append(formula4);
X14.ConditionalFormattingValueObject conditionalFormattingValueObject5 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula5 = new Excel.Formula();
formula5.Text = "80";
conditionalFormattingValueObject5.Append(formula5);
X14.ConditionalFormattingIcon conditionalFormattingIcon1 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeSymbols, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon2 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTrafficLights1, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon3 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon4 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)1U };
X14.ConditionalFormattingIcon conditionalFormattingIcon5 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)2U };
iconSet1.Append(conditionalFormattingValueObject1);
iconSet1.Append(conditionalFormattingValueObject2);
iconSet1.Append(conditionalFormattingValueObject3);
iconSet1.Append(conditionalFormattingValueObject4);
iconSet1.Append(conditionalFormattingValueObject5);
iconSet1.Append(conditionalFormattingIcon1);
iconSet1.Append(conditionalFormattingIcon2);
iconSet1.Append(conditionalFormattingIcon3);
iconSet1.Append(conditionalFormattingIcon4);
iconSet1.Append(conditionalFormattingIcon5);
conditionalFormattingRule1.Append(iconSet1);
Excel.ReferenceSequence referenceSequence1 = new Excel.ReferenceSequence();
referenceSequence1.Text = "A1:C201";
conditionalFormatting1.Append(conditionalFormattingRule1);
conditionalFormatting1.Append(referenceSequence1);
conditionalFormattings1.Append(conditionalFormatting1);
worksheetExtension1.Append(conditionalFormattings1);
worksheetExtensionList1.Append(worksheetExtension1);
....
worksheet1.Append(worksheetExtensionList1);
Option 2 would be to do as you are asking and perform string manipulation. This is much easier but it is a slightly dirty in that you are messing with strings rather then objects but if the only thing you need to set is the cell range that doesnt seem so bad. I used the test method above to extract the string with = extensionlistnode.OuterXml:
[TestMethod]
public void Custom_Condition_From_String_Test()
{
//http://stackoverflow.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus
//Throw in some data
var datatable = new DataTable("tblData");
datatable.Columns.Add(new DataColumn("Col1", typeof(int)));
datatable.Columns.Add(new DataColumn("Col2", typeof(int)));
datatable.Columns.Add(new DataColumn("Col3", typeof(int)));
for (var i = 0; i < 20; i++)
{
var row = datatable.NewRow();
row["Col1"] = i;
row["Col2"] = i * 10;
row["Col3"] = i * 100;
datatable.Rows.Add(row);
}
//Copy of the file with the conditonal formatting removed
var existingFile2 = new FileInfo(#"c:\temp\temp2.xlsx");
if (existingFile2.Exists)
existingFile2.Delete();
using (var package2 = new ExcelPackage(existingFile2))
{
//Add the data
var ws = package2.Workbook.Worksheets.Add("Content");
ws.Cells.LoadFromDataTable(datatable, true);
//The XML String extracted from the orginal excel doc using '= extensionlistnode.OuterXml'
var cellrange = "A1:C201";
var rawxml = String.Format(
"<extLst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><ext uri=\"{{78C0D931-6437-407d-A8EE-F0AAD7539E65}}\" xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\"><x14:conditionalFormattings><x14:conditionalFormatting xmlns:xm=\"http://schemas.microsoft.com/office/excel/2006/main\"><x14:cfRule type=\"iconSet\" priority=\"2\" id=\"{{CD6B2710-0474-449D-881A-22CFE15D011D}}\"><x14:iconSet iconSet=\"5Arrows\" custom=\"1\"><x14:cfvo type=\"percent\"><xm:f>0</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>20</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>40</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>60</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>80</xm:f></x14:cfvo><x14:cfIcon iconSet=\"3Symbols\" iconId=\"0\" /><x14:cfIcon iconSet=\"3TrafficLights1\" iconId=\"0\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"0\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"1\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"2\" /></x14:iconSet></x14:cfRule><xm:sqref>{0}</xm:sqref></x14:conditionalFormatting></x14:conditionalFormattings></ext></extLst>"
, cellrange);
var newxdoc = new XmlDocument();
newxdoc.LoadXml(rawxml);
//Create the import node and append it to the end of the xml document
var xdoc2 = ws.WorksheetXml;
var newnode = xdoc2.ImportNode(newxdoc.FirstChild, true);
xdoc2.LastChild.AppendChild(newnode);
package2.Save();
}
}
I have a scenario where I have Datagrid in my Silverlight application and I want the data to be exported to Power Point.
I researched and found only links, to export image(screen captured) to powerpoint. In my scenario , a screen capture also wont work as I have scroll bar with 20 columns and it is not getting displayed with the above solution.
Any work around for this scenario.
P.S : I do not intend to use any 3rd party controls.
Edit :
I have now tried to use OpenXML , but i am getting an error as below :
My code is as below :
using A = DocumentFormat.OpenXml.Drawing;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using P = DocumentFormat.OpenXml.Presentation;
using D = DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Drawing;
public static void CreateTableInLastSlide(PresentationDocument presentationDocument)
{
// Get the presentation Part of the presentation document
PresentationPart presentationPart = presentationDocument.PresentationPart;
// Get the Slide Id collection of the presentation document
var slideIdList = presentationPart.Presentation.SlideIdList;
if (slideIdList == null)
{
throw new NullReferenceException("The number of slide is empty, please select a ppt with a slide at least again");
}
// Get all Slide Part of the presentation document
var list = slideIdList.ChildElements
.Cast<SlideId>()
.Select(x => presentationPart.GetPartById(x.RelationshipId))
.Cast<SlidePart>();
// Get the last Slide Part of the presentation document
var tableSlidePart = (SlidePart)list.Last();
// Declare and instantiate the graphic Frame of the new slide
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());
ApplicationNonVisualDrawingPropertiesExtension applicationNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension();
P14.ModificationId modificationId1 = new P14.ModificationId() { Val = 3229994563U };
modificationId1.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
applicationNonVisualDrawingPropertiesExtension.Append(modificationId1);
graphicFrame.NonVisualGraphicFrameProperties = new DocumentFormat.OpenXml.Presentation.NonVisualGraphicFrameProperties
(new A.NonVisualDrawingProperties() { Id = 5, Name = "table 1" },
new A.NonVisualGraphicFrameDrawingProperties(new A.GraphicFrameLocks() { NoGrouping = true }),
new ApplicationNonVisualDrawingProperties(new ApplicationNonVisualDrawingPropertiesExtensionList(applicationNonVisualDrawingPropertiesExtension)));
graphicFrame.Transform = new Transform(new Offset() { X = 10, Y = 10 });
graphicFrame.Graphic = new A.Graphic(new A.GraphicData(GenerateTable()) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/table" });
presentationPart.Presentation.Save();
}
private static A.Table GenerateTable()
{
string[,] tableSources = new string[,] { { "name", "age" }, { "Tom", "25" } };
// Declare and instantiate table
A.Table table = new A.Table();
// Specify the required table properties for the table
A.TableProperties tableProperties = new A.TableProperties() { FirstRow = true, BandRow = true };
A.TableStyleId tableStyleId = new A.TableStyleId();
tableStyleId.Text = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
tableProperties.Append(tableStyleId);
// Declare and instantiate tablegrid and colums
A.TableGrid tableGrid1 = new A.TableGrid();
A.GridColumn gridColumn1 = new A.GridColumn() { Width = 3048000L };
A.GridColumn gridColumn2 = new A.GridColumn() { Width = 3048000L };
tableGrid1.Append(gridColumn1);
tableGrid1.Append(gridColumn2);
table.Append(tableProperties);
table.Append(tableGrid1);
for (int row = 0; row < tableSources.GetLength(0); row++)
{
// Instantiate the table row
A.TableRow tableRow = new A.TableRow() { Height = 370840L };
for (int column = 0; column < tableSources.GetLength(1); column++)
{
tableRow.Append(CreateTextCell(tableSources.GetValue(row, column).ToString()));
}
table.Append(tableRow);
}
return table;
}
Am i using the correct graphics and transform ??
The line which is causing the problem according to me is :
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame());
As if i comment his line i dont get the error, but neither do i get the table :o/
Any help ?
Finally i was able to solve the problem using the Open XML productivity tool (here) . The line i highlighted was the error. I needed to add the below code :
List<OpenXmlElement> elements = new List<OpenXmlElement>();
elements.Add(new P.NonVisualGraphicFrameProperties
(new P.NonVisualDrawingProperties() { Id = 1, Name = "xyz" }, new P.NonVisualGraphicFrameDrawingProperties(),new ApplicationNonVisualDrawingProperties()));
P.GraphicFrame graphicFrame = tableSlidePart.Slide.CommonSlideData.ShapeTree.AppendChild(new P.GraphicFrame(elements));
Thus i was able to get output without any errors :)