c# EPPlus: how to fix - ShowFilter doesn't work - epplus

The issue with Table.ShowFilter, using EPPLUS library.
Created new ExcelTable in the sheet, but can't apply Table.ShowFilter = false.
The filters are still in the table.
TableStyle and StyleName work fine.
ExcelTable et = (ExcelTable)Table;
int firstRow = newRow;
int lastRow;
if (DataStructure.Data != null)
lastRow = newRow + DataStructure.Data.Count();
else
lastRow = newRow + 1;
int firstColumn = OriginalAddress.StartColumn;
int lastColumn = OriginalAddress.EndColumn;
ExcelRange rg = ws.Cells[firstRow, firstColumn, lastRow, lastColumn];
Guid guid = Guid.NewGuid();
string str_guid = guid.ToString();
string tableName = et.Name + "_" + str_guid;
ExcelTable tab = wsTarget.Tables.Add(rg, tableName);
// tab.ShowHeader = et.ShowHeader;
// tab.TableStyle = et.TableStyle;
// tab.StyleName = et.StyleName;
tab.ShowFilter = false;
Right table is desired result.
Please, help to fix!

Is this you want to mean?
tab.ShowHeader = false;
This very little example works here :
using (ExcelPackage xls = new ExcelPackage())
{
ExcelWorksheet ws2 = xls.Workbook.Worksheets.Add("f1");
OfficeOpenXml.Table.ExcelTable tab = ws2.Tables.Add(new ExcelAddressBase("a1:e5"), "table");
//tab.TableStyle = et.TableStyle;
//tab.StyleName = et.StyleName;
tab.ShowFilter = false;
FileInfo f = new FileInfo(#"d:\temp\test.xlsx");
xls.SaveAs(f);
}

Probably, the bug.
Adding ws2.DeleteColumn(1, 1) to the code, add filters to the table, even with tab.ShowFilter = false.
Workaround: put tab.ShowFilter = false right before file saving.
using (ExcelPackage xls = new ExcelPackage())
{
ExcelWorksheet ws2 = xls.Workbook.Worksheets.Add("f1");
OfficeOpenXml.Table.ExcelTable tab = ws2.Tables.Add(new ExcelAddressBase("d3:g8"), "table");
//tab.TableStyle = et.TableStyle;
//tab.StyleName = et.StyleName;
ws2.DeleteColumn(1, 1);
tab.ShowFilter = false;
FileInfo f = new FileInfo(#"test.xlsx");
xls.SaveAs(f);
}

Related

How to change the style of the excel chart in vsto word addin?

how to change the style and how make x axis and y axis bold with differnt colour?
Word.Chart wdChart = doc.InlineShapes.AddChart(Microsoft.Office.Core.XlChartType.xlColumnClustered, ref missing).Chart;
wdChart.Legend.LegendEntries(wdChart.Legend.LegendEntries().Count).Delete();
wdChart.Legend.Clear();
wdChart.ChartStyle = 311;
Word.ChartData chartData = wdChart.ChartData;
Excel.Workbook dataWorkbook = (Excel.Workbook)chartData.Workbook;
Excel.Worksheet dataSheet = (Excel.Worksheet)dataWorkbook.Worksheets[1];
//wdChart.ChartTitle.Text = String.Empty;
dataWorkbook.Application.Visible = false;
for (int i = 0; i < xData.Count; i++)
{
((Excel.Range)dataSheet.Cells.get_Range("A" + (i + 2).ToString(), missing)).FormulaR1C1 = xData[i].ToString();
((Excel.Range)dataSheet.Cells.get_Range("B" + (i + 2).ToString(), missing)).FormulaR1C1 = yData[i].ToString();
((Excel.Range)dataSheet.Cells.get_Range("C" + (i + 2).ToString(), missing)).FormulaR1C1 = zData[i].ToString();
}
wdChart.HasTitle = false;
dataWorkbook.Application.Quit();

Cannot find column 25 Exception coming

I am creating one report where data exported from my access database to excel here. I'm not using any datagridview , when user click one checkbox appropriate report he can able to download for this I have written code but when I run this code its giving me Cannot find column 25, I don't know why its showing me this?
In access table I have total 25 column :
string sql = null;
string data = null;
int i = 0;
int j = 0;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
string connectionString = null;
connectionString = ConfigurationManager.ConnectionStrings["AccessConnectionString"].ConnectionString;
cnn.ConnectionString = connectionString;
cnn.Open();
sql = "SELECT * FROM Billing WHERE Bill_No and Bill_Date is null order by FormNo desc";
OleDbDataAdapter dscmd = new OleDbDataAdapter(sql, cnn);
DataSet ds = new DataSet();
dscmd.Fill(ds);
cnn.Close();
for (j = 0; i < ds.Tables[0].Columns.Count; j++)
{
xlWorkSheet.Cells[1, j + 1] = ds.Tables[0].Columns[j].Caption; // Exception coming this line
}
for (i = 0; i < ds.Tables[0].Rows.Count; i++)
{
for (j = 0; j < ds.Tables[0].Columns.Count; j++)
{
data = ds.Tables[0].Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 2, j + 1] = data;
}
}
System.Windows.Forms.SaveFileDialog saveDlg = new System.Windows.Forms.SaveFileDialog();
saveDlg.InitialDirectory = #"C:\";
saveDlg.Filter = "Excel files (*.xls)|*.xls";
saveDlg.FilterIndex = 0;
saveDlg.RestoreDirectory = true;
saveDlg.Title = "Export Excel File To";
xlWorkBook.Close(true, misValue, misValue);
MessageBox.Show("File Downloaded successfully...");
xlApp.Quit();
}
i got the answer here i change my for loop
for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
for (j = 0; j <= ds.Tables[0].Columns.Count - 1; j++)
{
xlWorkSheet.Cells[1, j + 1] = ds.Tables[0].Columns[j].Caption;
data = ds.Tables[0].Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 2, j + 1] = data;
}
}

Run-time error 91: Object variable or With block variable not set

I'm using Access 2010 VBA that is returning a recordset from an IBM iSeries. I have the following loop to append the recordset to a local table:
'Loop through recordset and place values
Do While rsti401.EOF = False
Set rst401 = CurrentDb.OpenRecordset("tblLocal_SL401WK", dbOpenDynaset, dbSeeChanges)
With rst401
.AddNew
.Fields("PC") = rsti401.Fields("PC")
.Fields("TIME") = rsti401.Fields("TIME")
.Fields("CONO") = rsti401.Fields("CONO")
.Fields("STYCOL") = rsti401.Fields("STYCOL")
.Fields("WHSE") = rsti401.Fields("WHSE")
.Fields("CUNO") = rsti401.Fields("CUNO")
.Fields("SIZE01") = rsti401.Fields("SIZE01")
.Fields("SIZE02") = rsti401.Fields("SIZE02")
.Fields("SIZE03") = rsti401.Fields("SIZE03")
.Fields("SIZE04") = rsti401.Fields("SIZE04")
.Fields("SIZE05") = rsti401.Fields("SIZE05")
.Fields("SIZE06") = rsti401.Fields("SIZE06")
.Fields("SIZE07") = rsti401.Fields("SIZE07")
.Fields("SIZE08") = rsti401.Fields("SIZE08")
.Fields("SIZE09") = rsti401.Fields("SIZE09")
.Fields("SIZE10") = rsti401.Fields("SIZE10")
.Fields("SIZE11") = rsti401.Fields("SIZE11")
.Fields("SIZE12") = rsti401.Fields("SIZE12")
.Fields("SIZE13") = rsti401.Fields("SIZE13")
.Fields("SIZE14") = rsti401.Fields("SIZE14")
.Fields("SIZE15") = rsti401.Fields("SIZE15")
.Fields("BQTY01") = rsti401.Fields("BQTY01")
.Fields("BQTY02") = rsti401.Fields("BQTY02")
.Fields("BQTY03") = rsti401.Fields("BQTY03")
.Fields("BQTY04") = rsti401.Fields("BQTY04")
.Fields("BQTY05") = rsti401.Fields("BQTY05")
.Fields("BQTY06") = rsti401.Fields("BQTY06")
.Fields("BQTY07") = rsti401.Fields("BQTY07")
.Fields("BQTY08") = rsti401.Fields("BQTY08")
.Fields("BQTY09") = rsti401.Fields("BQTY09")
.Fields("BQTY10") = rsti401.Fields("BQTY10")
.Fields("BQTY11") = rsti401.Fields("BQTY11")
.Fields("BQTY12") = rsti401.Fields("BQTY12")
.Fields("BQTY13") = rsti401.Fields("BQTY13")
.Fields("BQTY14") = rsti401.Fields("BQTY14")
.Fields("BQTY15") = rsti401.Fields("BQTY15")
.Update
End With
rsti401.MoveNext
Loop
'close connections
rsti401.Close
rst401.Close
IBM.Close
Set IBM = Nothing
Set rst401 = Nothing
Set rsti401 = Nothing
Set CMD = Nothing
However, each time I run it I is stopping at the following line:
rst401.Close
With error 'Run-time error 91'. I can't work it out. I've set rst401 at the beginning, so why am I still getting the error.
Any pointers would be a great help.
Thanks,
Michael
The problem you have is because the rst401 is set inside the Do While Loop, and you are trying to close an object that has lost its scope outside the Loop. Suggest you make the following changes.
'Loop through recordset and place values
Set rst401 = CurrentDb.OpenRecordset("tblLocal_SL401WK", dbOpenDynaset, dbSeeChanges)
Do While rsti401.EOF = False
With rst401
.AddNew
.Fields("PC") = rsti401.Fields("PC")
.Fields("TIME") = rsti401.Fields("TIME")
.Fields("CONO") = rsti401.Fields("CONO")
.Fields("STYCOL") = rsti401.Fields("STYCOL")
.Fields("WHSE") = rsti401.Fields("WHSE")
.Fields("CUNO") = rsti401.Fields("CUNO")
.Fields("SIZE01") = rsti401.Fields("SIZE01")
.Fields("SIZE02") = rsti401.Fields("SIZE02")
.Fields("SIZE03") = rsti401.Fields("SIZE03")
.Fields("SIZE04") = rsti401.Fields("SIZE04")
.Fields("SIZE05") = rsti401.Fields("SIZE05")
.Fields("SIZE06") = rsti401.Fields("SIZE06")
.Fields("SIZE07") = rsti401.Fields("SIZE07")
.Fields("SIZE08") = rsti401.Fields("SIZE08")
.Fields("SIZE09") = rsti401.Fields("SIZE09")
.Fields("SIZE10") = rsti401.Fields("SIZE10")
.Fields("SIZE11") = rsti401.Fields("SIZE11")
.Fields("SIZE12") = rsti401.Fields("SIZE12")
.Fields("SIZE13") = rsti401.Fields("SIZE13")
.Fields("SIZE14") = rsti401.Fields("SIZE14")
.Fields("SIZE15") = rsti401.Fields("SIZE15")
.Fields("BQTY01") = rsti401.Fields("BQTY01")
.Fields("BQTY02") = rsti401.Fields("BQTY02")
.Fields("BQTY03") = rsti401.Fields("BQTY03")
.Fields("BQTY04") = rsti401.Fields("BQTY04")
.Fields("BQTY05") = rsti401.Fields("BQTY05")
.Fields("BQTY06") = rsti401.Fields("BQTY06")
.Fields("BQTY07") = rsti401.Fields("BQTY07")
.Fields("BQTY08") = rsti401.Fields("BQTY08")
.Fields("BQTY09") = rsti401.Fields("BQTY09")
.Fields("BQTY10") = rsti401.Fields("BQTY10")
.Fields("BQTY11") = rsti401.Fields("BQTY11")
.Fields("BQTY12") = rsti401.Fields("BQTY12")
.Fields("BQTY13") = rsti401.Fields("BQTY13")
.Fields("BQTY14") = rsti401.Fields("BQTY14")
.Fields("BQTY15") = rsti401.Fields("BQTY15")
.Update
End With
rsti401.MoveNext
Loop
'close connections
rsti401.Close
rst401.Close
IBM.Close
Set IBM = Nothing
Set rst401 = Nothing
Set rsti401 = Nothing
Set CMD = Nothing

Show WinForm below a cell

How can I show I winform that I create in VB.NET just below the active cell?
I have no idea how to solve this. I found the following promising solutions:
Excel addin: Cell absolute position
-The accepted solution seems too complicated to work reliably. I got an error on the first row (Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long)
-The second solution looked promising, but it didn't give me the right positions for my windows form.
The following adaptations of the second proposed solution does not create any errors but does not put the windows form in the correct position:
Public Sub GetScreenPositionFromCell(cell As Excel.Range, excel As Excel.Application)
Dim x As Double
Dim y As Double
If Not excel.ActiveWindow Is Nothing Then
x = excel.ActiveWindow.PointsToScreenPixelsX(cell.Left)
y = excel.ActiveWindow.PointsToScreenPixelsY(cell.Top)
End If
Me.Left = x
Me.Top = y
Me.Show()
Me.TopMost = True
End Sub
EDIT: #Loating, here is how I have used your code. It's great and I am very happy that you are taking your time to help me with a solution. The x-coordinates seems to work while the x-coordinates are a bit off and more or less off depending on the zoom level.
Public Sub ShowMeBelowActiveCell()
Dim ExcelApp As Excel.Application = CType(AddinExpress.MSO.ADXAddinModule.CurrentInstance, AddinModule).ExcelApp
Dim excelWindow = ExcelApp.ActiveWindow
Dim cell = ExcelApp.ActiveCell
Dim zoomFactor As Double = excelWindow.Zoom / 100
Dim ws = cell.Worksheet
' PointsToScreenPixels returns different values if the scroll is not currently 1
' Temporarily set the scroll back to 1 so that PointsToScreenPixels returns a
' value we know how to handle.
Dim origScrollCol = excelWindow.ScrollColumn
Dim origScrollRow = excelWindow.ScrollRow
excelWindow.ScrollColumn = 1
excelWindow.ScrollRow = 1
' (x,y) are screen coordinates for the top left corner of the top left cell
Dim x As Integer = excelWindow.PointsToScreenPixelsX(0)
' e.g. window.x + row header width
Dim y As Integer = excelWindow.PointsToScreenPixelsY(0)
' e.g. window.y + ribbon height + column headers height
Dim dpiX As Single = 0
Dim dpiY As Single = 0
Using g = Drawing.Graphics.FromHwnd(IntPtr.Zero)
dpiX = g.DpiX
dpiY = g.DpiY
End Using
' Note: Each column width / row height has to be calculated individually.
' Before, tried to use this approach:
' var r2 = (Microsoft.Office.Interop.Excel.Range) cell.Worksheet.Cells[origScrollRow, origScrollCol];
' double dw = cell.Left - r2.Left;
' double dh = cell.Top - r2.Top;
' However, that only works when the zoom factor is a whole number.
' A fractional zoom (e.g. 1.27) causes each individual row or column to round to the closest whole number,
' which means having to loop through.
For i As Integer = origScrollCol To cell.Column - 1
Dim col = DirectCast(ws.Cells(cell.Row, i), Microsoft.Office.Interop.Excel.Range)
Dim ww As Double = col.Width * dpiX / 72
Dim newW As Double = zoomFactor * ww
x += CInt(Math.Round(newW))
Next
For i As Integer = origScrollRow To cell.Row - 1
Dim row = DirectCast(ws.Cells(i, cell.Column), Microsoft.Office.Interop.Excel.Range)
Dim hh As Double = row.Height * dpiY / 72
Dim newH As Double = zoomFactor * hh
y += CInt(Math.Round(newH))
Next
excelWindow.ScrollColumn = origScrollCol
excelWindow.ScrollRow = origScrollRow
Me.StartPosition = Windows.Forms.FormStartPosition.Manual
Me.Location = New Drawing.Point(x, y)
Me.Show()
End Sub
End Class
When the ScrollColumn and ScrollRow are both 1, then PointsToScreenPixelsX/Y seems to return the top left point of the top left visible cell in screen coordinates. Using this, the offset width and height to the active cell is calculated, taking into consideration the zoom setting.
var excelApp = Globals.ThisAddIn.Application;
var excelWindow = excelApp.ActiveWindow;
var cell = excelApp.ActiveCell;
double zoomFactor = excelWindow.Zoom / 100;
var ws = cell.Worksheet;
var ap = excelWindow.ActivePane; // might be split panes
var origScrollCol = ap.ScrollColumn;
var origScrollRow = ap.ScrollRow;
excelApp.ScreenUpdating = false;
// when FreezePanes == true, ap.ScrollColumn/Row will only reset
// as much as the location of the frozen splitter
ap.ScrollColumn = 1;
ap.ScrollRow = 1;
// PointsToScreenPixels returns different values if the scroll is not currently 1
// Temporarily set the scroll back to 1 so that PointsToScreenPixels returns a
// value we know how to handle.
// (x,y) are screen coordinates for the top left corner of the top left cell
int x = ap.PointsToScreenPixelsX(0); // e.g. window.x + row header width
int y = ap.PointsToScreenPixelsY(0); // e.g. window.y + ribbon height + column headers height
float dpiX = 0;
float dpiY = 0;
using (var g = Graphics.FromHwnd(IntPtr.Zero)) {
dpiX = g.DpiX;
dpiY = g.DpiY;
}
int deltaRow = 0;
int deltaCol = 0;
int fromCol = origScrollCol;
int fromRow = origScrollRow;
if (excelWindow.FreezePanes) {
fromCol = 1;
fromRow = 1;
deltaCol = origScrollCol - ap.ScrollColumn; // Note: ap.ScrollColumn/Row <> 1
deltaRow = origScrollRow - ap.ScrollRow; // see comment: when FreezePanes == true ...
}
// Note: Each column width / row height has to be calculated individually.
// Before, tried to use this approach:
// var r2 = (Microsoft.Office.Interop.Excel.Range) cell.Worksheet.Cells[origScrollRow, origScrollCol];
// double dw = cell.Left - r2.Left;
// double dh = cell.Top - r2.Top;
// However, that only works when the zoom factor is a whole number.
// A fractional zoom (e.g. 1.27) causes each individual row or column to round to the closest whole number,
// which means having to loop through.
for (int i = fromCol; i < cell.Column; i++) {
// skip the columns between the frozen split and the first visible column
if (i >= ap.ScrollColumn && i < ap.ScrollColumn + deltaCol)
continue;
var col = ((Microsoft.Office.Interop.Excel.Range) ws.Cells[cell.Row, i]);
double ww = col.Width * dpiX / 72;
double newW = zoomFactor * ww;
x += (int) Math.Round(newW);
}
for (int i = fromRow; i < cell.Row; i++) {
// skip the columns between the frozen split and the first visible column
if (i >= ap.ScrollRow && i < ap.ScrollRow + deltaRow)
continue;
var row = ((Microsoft.Office.Interop.Excel.Range) ws.Cells[i, cell.Column]);
double hh = row.Height * dpiY / 72;
double newH = zoomFactor * hh;
y += (int) Math.Round(newH);
}
ap.ScrollColumn = origScrollCol;
ap.ScrollRow = origScrollRow;
excelApp.ScreenUpdating = true;
Form f = new Form();
f.StartPosition = FormStartPosition.Manual;
f.Location = new Point(x, y);
f.Show();

EPPlus Pivot Table - Copy Values to New Sheet

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?
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();
}