I've successfully created a pivot table using EPPlus. The pivot table resides in a seperate sheet from the raw data. I would like to copy the pivot table data to a new, third, sheet, but just the values, not the pivot defintions. Does EPPlus support this?
Asked
Active
Viewed 2,436 times
1 Answers
3
You can just copy the datasource range via Cache Definition:
public void PivotDataCopy()
{
const string FORMATCURRENCY = "#,###;[Red](#,###)";
var file = new FileInfo(@"c:\temp\temp.xlsx");
if (file.Exists)
file.Delete();
var pck = new ExcelPackage(file);
var workbook = pck.Workbook;
var dataworksheet = workbook.Worksheets.Add("datasheet");
//The data
dataworksheet.Cells["A20"].Value = "Col1";
dataworksheet.Cells["A21"].Value = "sdf";
dataworksheet.Cells["A22"].Value = "wer";
dataworksheet.Cells["A23"].Value = "ghgh";
dataworksheet.Cells["A24"].Value = "sdf";
dataworksheet.Cells["A25"].Value = "wer";
dataworksheet.Cells["B20"].Value = "Col2";
dataworksheet.Cells["B21"].Value = "Group A";
dataworksheet.Cells["B22"].Value = "Group B";
dataworksheet.Cells["B23"].Value = "Group A";
dataworksheet.Cells["B24"].Value = "Group C";
dataworksheet.Cells["B25"].Value = "Group A";
dataworksheet.Cells["C20"].Value = "Col3";
dataworksheet.Cells["C21"].Value = 453.5;
dataworksheet.Cells["C22"].Value = 634.5;
dataworksheet.Cells["C23"].Value = 274.5;
dataworksheet.Cells["C24"].Value = 453.5;
dataworksheet.Cells["C25"].Value = 634.5;
dataworksheet.Cells["D20"].Value = "Col4";
dataworksheet.Cells["D21"].Value = 686468;
dataworksheet.Cells["D22"].Value = 996440;
dataworksheet.Cells["D23"].Value = 185780;
dataworksheet.Cells["D24"].Value = 686468;
dataworksheet.Cells["D25"].Value = 996440;
//The pivot table
var pivotworksheet = workbook.Worksheets.Add("pivotsheet");
var pivotTable = pivotworksheet.PivotTables.Add(pivotworksheet.Cells["A1"], dataworksheet.Cells["A20:D29"], "test");
//The label row field
pivotTable.RowFields.Add(pivotTable.Fields["Col1"]);
pivotTable.DataOnRows = false;
//The data fields
var field = pivotTable.DataFields.Add(pivotTable.Fields["Col3"]);
field.Name = "Sum of Col2";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
field = pivotTable.DataFields.Add(pivotTable.Fields["Col4"]);
field.Name = "Sum of Col3";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
//Get the pivot table data source
var newworksheet = workbook.Worksheets.Add("newworksheet");
var pivotdatasourcerange = pivotTable.CacheDefinition.SourceRange;
pivotdatasourcerange.Copy(newworksheet.Cells["A1"]);
pck.Save();
}
EDIT: Doing with a VBA macro which then resaves the sheet as a non-macro XLSX:
public void PivotDataCopy()
{
const string FORMATCURRENCY = "#,###;[Red](#,###)";
var file = new FileInfo(@"c:\temp\temp.xlsm");
if (file.Exists)
file.Delete();
var pck = new ExcelPackage(file);
var workbook = pck.Workbook;
var dataworksheet = workbook.Worksheets.Add("datasheet");
//The data
dataworksheet.Cells["A20"].Value = "Col1";
dataworksheet.Cells["A21"].Value = "sdf";
dataworksheet.Cells["A22"].Value = "wer";
dataworksheet.Cells["A23"].Value = "ghgh";
dataworksheet.Cells["A24"].Value = "sdf";
dataworksheet.Cells["A25"].Value = "wer";
dataworksheet.Cells["B20"].Value = "Col2";
dataworksheet.Cells["B21"].Value = "Group A";
dataworksheet.Cells["B22"].Value = "Group B";
dataworksheet.Cells["B23"].Value = "Group A";
dataworksheet.Cells["B24"].Value = "Group C";
dataworksheet.Cells["B25"].Value = "Group A";
dataworksheet.Cells["C20"].Value = "Col3";
dataworksheet.Cells["C21"].Value = 453.5;
dataworksheet.Cells["C22"].Value = 634.5;
dataworksheet.Cells["C23"].Value = 274.5;
dataworksheet.Cells["C24"].Value = 453.5;
dataworksheet.Cells["C25"].Value = 634.5;
dataworksheet.Cells["D20"].Value = "Col4";
dataworksheet.Cells["D21"].Value = 686468;
dataworksheet.Cells["D22"].Value = 996440;
dataworksheet.Cells["D23"].Value = 185780;
dataworksheet.Cells["D24"].Value = 686468;
dataworksheet.Cells["D25"].Value = 996440;
//The pivot table
var pivotworksheet = workbook.Worksheets.Add("pivotsheet");
var pivotTable = pivotworksheet.PivotTables.Add(pivotworksheet.Cells["A1"], dataworksheet.Cells["A20:D29"], "test");
//The label row field
pivotTable.RowFields.Add(pivotTable.Fields["Col1"]);
pivotTable.DataOnRows = false;
//The data fields
var field = pivotTable.DataFields.Add(pivotTable.Fields["Col3"]);
field.Name = "Sum of Col2";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
field = pivotTable.DataFields.Add(pivotTable.Fields["Col4"]);
field.Name = "Sum of Col3";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
//add the macro to copy the table data on open
workbook.Worksheets.Add("newworksheet");
var sb = new StringBuilder();
sb.AppendLine("Private Sub Workbook_SheetCalculate(ByVal Sh As Object)");
sb.AppendLine(" Sheets(\"pivotsheet\").Cells.Copy");
sb.AppendLine(" Sheets(\"newworksheet\").Range(\"A1\").PasteSpecial Paste:=xlPasteValues");
sb.AppendLine(" Selection.Clear");
sb.AppendLine(" Application.DisplayAlerts = False");
sb.AppendLine(String.Format(" ActiveWorkbook.SaveAs \"{0}\", xlOpenXMLWorkbook", file.FullName.Replace("xlsm", "xlsx")));
sb.AppendLine(" Application.DisplayAlerts = True");
sb.AppendLine("End Sub");
pck.Workbook.CreateVBAProject();
pck.Workbook.CodeModule.Code = sb.ToString();
pck.Save();
}

Ernie S
- 13,902
- 4
- 52
- 79
-
Thanks Ernie. I will try that shortly. Will this only copy the values and not the pivot table defintion? I want to allow the user to edit the values on the new sheet. – Randy Minder Nov 04 '14 at 13:49
-
@RandyMinder It will do straight value copy to the new sheet so the pivot table will still be linked to the ORIGINAL data, not the copied. Based on your post I assumed that is what you wanted? – Ernie S Nov 04 '14 at 14:06
-
This is not doing what I want. Your code is making a copy of the source data, not the pivoted data. I want to copy the pivoted data values to a new sheet. – Randy Minder Nov 04 '14 at 14:14
-
@RandyMinder Sorry Randy, I misunderstood but understand now. Unfortunately, I dont think it can be done because EPPlus does not actually generated the pivot table itself and only creates the raw XML that defines it. It then relies on Excel when it first opens the file to fill in the content (sorry if you already know all of this). So the best I think you could do is generate the pivot table in EPP and use a VBA macro to copy/paste the data. Not the greatest solution because the macro complicates the security settings. Sorry I couldnt be more help. – Ernie S Nov 04 '14 at 14:57
-
@RandyMinder Added a new blob of code which shows how to do it with VBA if it is an option for you. – Ernie S Nov 04 '14 at 16:01
-
Thank you Ernie. What I'm really trying to do is to get at the pivoted data via C# so I can send the results back to the client. It doesn't appear I'm going to be able to do that. At least not using Excel as the pivoting mechanism. – Randy Minder Nov 04 '14 at 16:34
-
@RandyMinder Ahhh...I see. Ya, EPP doesnt look like a great option. If you have access to the full office excel DOM that would probably be your solution but I am guessing you dont (server?) which is why you considered EPP. Good luck. – Ernie S Nov 04 '14 at 16:54