From 18ffc1a8d5c1ada518fcc7ac306bcfb6d6537a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Wed, 7 Oct 2020 16:15:10 +0200 Subject: [PATCH 01/18] Version 5.4 samples --- .gitignore | 1 + 04-LoadingData/LoadingDataWithTablesSample.cs | 3 +- 04-LoadingData/testdata.json | 20 ++ 13-Filter/FilterSample.cs | 46 +++- 18-PivotTables/PivotTablesSample.cs | 258 ++++++++++++++---- 24-Slicers/Readme.md | 9 + 24-Slicers/SlicerSample.cs | 161 +++++++++++ EPPlus.Sample.NET.csproj | 9 +- Sample_Main.cs | 8 +- packages.config | 3 +- 10 files changed, 459 insertions(+), 59 deletions(-) create mode 100644 04-LoadingData/testdata.json create mode 100644 24-Slicers/Readme.md create mode 100644 24-Slicers/SlicerSample.cs diff --git a/.gitignore b/.gitignore index 4bcc661..76a6b4f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ obj/ Ankh.NoLoad *.[Pp]ublish.xml .vs/ +.vscode/ .nuget/nuget.exe *.orig diff --git a/04-LoadingData/LoadingDataWithTablesSample.cs b/04-LoadingData/LoadingDataWithTablesSample.cs index 5c21ffb..31fe516 100644 --- a/04-LoadingData/LoadingDataWithTablesSample.cs +++ b/04-LoadingData/LoadingDataWithTablesSample.cs @@ -21,7 +21,7 @@ Date Author Change using System.Reflection; using System.ComponentModel; -namespace EPPlusSamples.LoadingDataWithTables +namespace EPPlusSamples.LoadingData { /// /// This class shows how to load data in a few ways @@ -110,6 +110,7 @@ orderby file.Name ascending //...and save var fi = FileOutputUtil.GetFileInfo("04-LoadingData.xlsx"); pck.SaveAs(fi); + pck.Dispose(); } private static DataTable GetDataTable(DirectoryInfo dir) { diff --git a/04-LoadingData/testdata.json b/04-LoadingData/testdata.json new file mode 100644 index 0000000..f7c2a43 --- /dev/null +++ b/04-LoadingData/testdata.json @@ -0,0 +1,20 @@ +[ + { + "Id": 1, + "FirstName": "Bob", + "LastName": "Behnken", + "LastSpaceFlight" : "2020-05-30T19:22:45" + }, + { + "Id": 2, + "FirstName": "Doug", + "LastName": "Hurley", + "LastSpaceFlight": "2020-05-30T19:22:45" + }, + { + "Id": 3, + "FirstName": "Neil", + "LastName": "Armstrong", + "LastSpaceFlight": "1969-07-16T13:32:00" + } +] diff --git a/13-Filter/FilterSample.cs b/13-Filter/FilterSample.cs index 86b50c9..092ced6 100644 --- a/13-Filter/FilterSample.cs +++ b/13-Filter/FilterSample.cs @@ -13,6 +13,7 @@ Date Author Change using EPPlusSamples; using OfficeOpenXml; using OfficeOpenXml.Filter; +using OfficeOpenXml.Table.PivotTable; using System; using System.Data.SQLite; using System.Net.Http; @@ -35,9 +36,11 @@ public static async Task RunAsync(string connectionString) await DynamicAboveAverageFilter(connectionString, p); await DynamicDateAugustFilter(connectionString, p); - //Filter on a table + //Filter on a table, also see sample 24-Slicers. await TableFilter(connectionString, p); - + + //Filter on a pivot table, also see sample 24-Slicers. + await PivotTableFilter(connectionString, p); p.SaveAs(FileOutputUtil.GetFileInfo("13-Filters.xlsx")); } @@ -135,6 +138,45 @@ private static async Task TableFilter(string connectionString, ExcelPackage p) tbl.AutoFilter.ApplyFilter(); range.AutoFitColumns(0); } + private static async Task PivotTableFilter(string connectionString, ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("PivotTableFilter"); + ExcelRangeBase range = await LoadFromDatabase(connectionString, ws); + + var tbl = ws.Tables.Add(range, "ptFilter"); + tbl.TableStyle = OfficeOpenXml.Table.TableStyles.Medium23; + + var pt1=ws.PivotTables.Add(ws.Cells["J1"], tbl, "PivotTable1"); + var rowField = pt1.RowFields.Add(pt1.Fields["CompanyName"]); + var dataField = pt1.DataFields.Add(pt1.Fields["OrderValue"]); + + //First deselect a company in the items list. To do so we first need to refresh the items from the range. + rowField.Items.Refresh(); //Refresh the items from the range. + rowField.Items.GetByValue("Sporer, Mertz and Jaskolski").Hidden=true; + //Add a caption filter on Company Name between A and D + rowField.Filters.AddCaptionFilter(ePivotTableCaptionFilterType.CaptionBetween, "A", "D"); + //Add a value filter where OrderValue >= 100 + rowField.Filters.AddValueFilter(ePivotTableValueFilterType.ValueGreaterThanOrEqual, dataField, 100); + + //Add a second pivot table with some different filters. + var pt2 = ws.PivotTables.Add(ws.Cells["M1"], tbl, "PivotTable2"); + var rowField1 = pt2.RowFields.Add(pt2.Fields["Currency"]); + var rowField2 = pt2.RowFields.Add(pt2.Fields["OrderDate"]); + rowField2.Format = "yyyy-MM-dd"; + var dataField1 = pt2.DataFields.Add(pt2.Fields["OrderValue"]); + var dataField2 = pt2.DataFields.Add(pt2.Fields["OrderId"]); + dataField2.Function = DataFieldFunctions.CountNums; + + var slicer = rowField1.AddSlicer(); + slicer.SetPosition(11, 0, 9, 0); + //Add a date filter between first of Mars 2017 to 30th of June + rowField2.Filters.AddDateValueFilter(ePivotTableDateValueFilterType.DateBetween, new DateTime(2017, 3, 1), new DateTime(2017, 6, 30)); + //Add a filter on the bottom 25 percent of the OrderValue + rowField2.Filters.AddTop10Filter(ePivotTableTop10FilterType.Percent, dataField1, 25, false); + pt2.DataOnRows = false; + + range.AutoFitColumns(0); + } private static async Task LoadFromDatabase(string connectionString, ExcelWorksheet ws) { diff --git a/18-PivotTables/PivotTablesSample.cs b/18-PivotTables/PivotTablesSample.cs index 4b7526e..7d1051f 100644 --- a/18-PivotTables/PivotTablesSample.cs +++ b/18-PivotTables/PivotTablesSample.cs @@ -54,69 +54,223 @@ public static string Run(string connectionStr) var dataRange = wsData.Cells["A1"].LoadFromCollection ( - from s in list + from s in list orderby s.Name - select s, - true, OfficeOpenXml.Table.TableStyles.Medium2); - + select s, + true, OfficeOpenXml.Table.TableStyles.Medium2); + wsData.Cells[2, 6, dataRange.End.Row, 6].Style.Numberformat.Format = "mm-dd-yy"; wsData.Cells[2, 7, dataRange.End.Row, 11].Style.Numberformat.Format = "#,##0"; - + dataRange.AutoFitColumns(); - var wsPivot = pck.Workbook.Worksheets.Add("PivotSimple"); - var pivotTable1 = wsPivot.PivotTables.Add(wsPivot.Cells["A1"], dataRange, "PerCountry"); - - pivotTable1.RowFields.Add(pivotTable1.Fields["Country"]); - var dataField = pivotTable1.DataFields.Add(pivotTable1.Fields["OrderValue"]); - dataField.Format="#,##0"; - pivotTable1.DataOnRows = true; - - var chart = wsPivot.Drawings.AddPieChart("PivotChart", ePieChartType.PieExploded3D, pivotTable1); - chart.SetPosition(1, 0, 4, 0); - chart.SetSize(800, 600); - chart.Legend.Remove(); - chart.Series[0].DataLabel.ShowCategory = true; - chart.Series[0].DataLabel.Position = eLabelPosition.OutEnd; - chart.StyleManager.SetChartStyle(ePresetChartStyle.Pie3dChartStyle6); - - var wsPivot2 = pck.Workbook.Worksheets.Add("PivotDateGrp"); - var pivotTable2 = wsPivot2.PivotTables.Add(wsPivot2.Cells["A3"], dataRange, "PerEmploeeAndQuarter"); - - pivotTable2.RowFields.Add(pivotTable2.Fields["Name"]); - - //Add a rowfield - var rowField = pivotTable2.RowFields.Add(pivotTable2.Fields["OrderDate"]); - //This is a date field so we want to group by Years and quaters. This will create one additional field for years. - rowField.AddDateGrouping(eDateGroupBy.Years | eDateGroupBy.Quarters); - //Get the Quaters field and change the texts - var quaterField = pivotTable2.Fields.GetDateGroupField(eDateGroupBy.Quarters); - quaterField.Items[0].Text = "<"; //Values below min date, but we use auto so its not used - quaterField.Items[1].Text = "Q1"; - quaterField.Items[2].Text = "Q2"; - quaterField.Items[3].Text = "Q3"; - quaterField.Items[4].Text = "Q4"; - quaterField.Items[5].Text = ">"; //Values above max date, but we use auto so its not used - - //Add a pagefield - var pageField = pivotTable2.PageFields.Add(pivotTable2.Fields["CompanyName"]); - - //Add the data fields and format them - dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["OrderValue"]); - dataField.Format = "#,##0"; - dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["Tax"]); - dataField.Format = "#,##0"; - dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["Freight"]); - dataField.Format = "#,##0"; - - //We want the datafields to appear in columns - pivotTable2.DataOnRows = false; + var pt1 = CreatePivotTableWithPivotChart(pck, dataRange); + var pt2 = CreatePivotTableWithDataGrouping(pck, dataRange); + var pt3 = CreatePivotTableWithPageFilter(pck, pt2.CacheDefinition); + var pt4 = CreatePivotTableWithASlicer(pck, pt2.CacheDefinition); + var pt5 = CreatePivotTableWithACalculatedField(pck, pt2.CacheDefinition); + + //Filter samples + var pt6 = CreatePivotTableCaptionFilter(pck, dataRange); pck.Save(); } return newFile.FullName; } + private static ExcelPivotTable CreatePivotTableWithPivotChart(ExcelPackage pck, ExcelRangeBase dataRange) + { + var wsPivot = pck.Workbook.Worksheets.Add("PivotSimple"); + var pivotTable = wsPivot.PivotTables.Add(wsPivot.Cells["A1"], dataRange, "PerCountry"); + + pivotTable.RowFields.Add(pivotTable.Fields["Country"]); + var dataField = pivotTable.DataFields.Add(pivotTable.Fields["OrderValue"]); + dataField.Format = "#,##0"; + pivotTable.DataOnRows = true; + + var chart = wsPivot.Drawings.AddPieChart("PivotChart", ePieChartType.PieExploded3D, pivotTable); + chart.SetPosition(1, 0, 4, 0); + chart.SetSize(800, 600); + chart.Legend.Remove(); + chart.Series[0].DataLabel.ShowCategory = true; + chart.Series[0].DataLabel.Position = eLabelPosition.OutEnd; + chart.StyleManager.SetChartStyle(ePresetChartStyle.Pie3dChartStyle6); + return pivotTable; + } + + private static ExcelPivotTable CreatePivotTableWithDataGrouping(ExcelPackage pck, ExcelRangeBase dataRange) + { + var wsPivot2 = pck.Workbook.Worksheets.Add("PivotDateGrp"); + var pivotTable2 = wsPivot2.PivotTables.Add(wsPivot2.Cells["A3"], dataRange, "PerEmploeeAndQuarter"); + + pivotTable2.RowFields.Add(pivotTable2.Fields["Name"]); + + //Add a rowfield + var rowField = pivotTable2.RowFields.Add(pivotTable2.Fields["OrderDate"]); + //This is a date field so we want to group by Years and quaters. This will create one additional field for years. + rowField.AddDateGrouping(eDateGroupBy.Years | eDateGroupBy.Quarters); + //Get the Quaters field and change the texts + var quaterField = pivotTable2.Fields.GetDateGroupField(eDateGroupBy.Quarters); + quaterField.Items[0].Text = "<"; //Values below min date, but we use auto so its not used + quaterField.Items[1].Text = "Q1"; + quaterField.Items[2].Text = "Q2"; + quaterField.Items[3].Text = "Q3"; + quaterField.Items[4].Text = "Q4"; + quaterField.Items[5].Text = ">"; //Values above max date, but we use auto so its not used + + //Add a pagefield + var pageField = pivotTable2.PageFields.Add(pivotTable2.Fields["CompanyName"]); + + //Add the data fields and format them + ExcelPivotTableDataField dataField; + dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["OrderValue"]); + dataField.Format = "#,##0"; + dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["Tax"]); + dataField.Format = "#,##0"; + dataField = pivotTable2.DataFields.Add(pivotTable2.Fields["Freight"]); + dataField.Format = "#,##0"; + + //We want the datafields to appear in columns + pivotTable2.DataOnRows = false; + return pivotTable2; + } + private static ExcelPivotTable CreatePivotTableWithPageFilter(ExcelPackage pck, ExcelPivotCacheDefinition pivotCache) + { + var wsPivot3 = pck.Workbook.Worksheets.Add("PivotWithPageField"); + + //Create a new pivot table using the same cache as pivot table 2. + var pivotTable3 = wsPivot3.PivotTables.Add(wsPivot3.Cells["A3"], pivotCache, "PerEmploeeSelectedCompanies"); + + pivotTable3.RowFields.Add(pivotTable3.Fields["Name"]); + + //Add a rowfield + var rowField = pivotTable3.RowFields.Add(pivotTable3.Fields["OrderDate"]); + + //Add a pagefield + var pageField = pivotTable3.PageFields.Add(pivotTable3.Fields["CompanyName"]); + pageField.Items.Refresh(); //Refresh the items from the source range. + + pageField.Items[1].Hidden = true; //Hide item with index 1 in the items collection + pageField.Items.GetByValue("Walsh LLC").Hidden = true; //Hide the item with supplied the value . + //pageField.Items.SelectSingleItem(3); //You can also select a single item with this method + + //Add the data fields and format them + ExcelPivotTableDataField dataField; + dataField = pivotTable3.DataFields.Add(pivotTable3.Fields["OrderValue"]); + dataField.Format = "#,##0"; + dataField = pivotTable3.DataFields.Add(pivotTable3.Fields["Tax"]); + dataField.Format = "#,##0"; + dataField = pivotTable3.DataFields.Add(pivotTable3.Fields["Freight"]); + dataField.Format = "#,##0"; + + + //We want the datafields to appear in columns + pivotTable3.DataOnRows = false; + return pivotTable3; + } + private static ExcelPivotTable CreatePivotTableWithASlicer(ExcelPackage pck, ExcelPivotCacheDefinition pivotCache) + { + //This method connects a slicer to the pivot table. Also see sample 24 for more detailed samples on slicers. + var wsPivot4 = pck.Workbook.Worksheets.Add("PivotWithSlicer"); + + //Create a new pivot table using the same cache as pivot table 2. + var pivotTable4 = wsPivot4.PivotTables.Add(wsPivot4.Cells["A3"], pivotCache, "PerEmploeeSelectedCompSlicer"); + + pivotTable4.RowFields.Add(pivotTable4.Fields["Name"]); + + //Add a rowfield + pivotTable4.RowFields.Add(pivotTable4.Fields["OrderDate"]); + + //Add slicer + var companyNameField = pivotTable4.Fields["CompanyName"]; + var slicer = companyNameField.AddSlicer(); + slicer.SetPosition(3, 0, 5, 0); //Set top left to row 4, column F + + companyNameField.Items.Refresh(); //Refresh the items from the source range. + + companyNameField.Items[1].Hidden = true; //Hide item with index 1 in the items collection + companyNameField.Items.GetByValue("Walsh LLC").Hidden = true; //Hide the item with supplied the value . + + //Add the data fields and format them + ExcelPivotTableDataField dataField; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["OrderValue"]); + dataField.Format = "#,##0"; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["Tax"]); + dataField.Format = "#,##0"; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["Freight"]); + dataField.Format = "#,##0"; + + //We want the data fields to appear in columns + pivotTable4.DataOnRows = false; + return pivotTable4; + } + private static ExcelPivotTable CreatePivotTableWithACalculatedField(ExcelPackage pck, ExcelPivotCacheDefinition pivotCache) + { + //This method connects a slicer to the pivot table. Also see sample 24 for more detailed samples on slicers. + var wsPivot4 = pck.Workbook.Worksheets.Add("PivotWithCalculatedField"); + + //Create a new pivot table using the same cache as pivot table 2. + var pivotTable4 = wsPivot4.PivotTables.Add(wsPivot4.Cells["A3"], pivotCache, "PerWithCalculatedField"); + + pivotTable4.RowFields.Add(pivotTable4.Fields["CompanyName"]); + pivotTable4.RowFields.Add(pivotTable4.Fields["OrderDate"]); + + //Be carfull with formulas as they are not validated and can cause the pivot table to become corrupt. + var calcField = pivotTable4.Fields.AddCalculatedField("Total", "'OrderValue'+'Tax'+'Freight'"); + calcField.Format = "#,##0"; + + //Add the data fields and format them + ExcelPivotTableDataField dataField; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["OrderValue"]); + dataField.Format = "#,##0"; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["Tax"]); + dataField.Format = "#,##0"; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["Freight"]); + dataField.Format = "#,##0"; + dataField = pivotTable4.DataFields.Add(pivotTable4.Fields["Total"]); + dataField.Format = "#,##0"; + + + //We want the data fields to appear in columns + pivotTable4.DataOnRows = false; + return pivotTable4; + } + private static ExcelPivotTable CreatePivotTableCaptionFilter(ExcelPackage pck, ExcelRangeBase dataRange) + { + var wsPivot4 = pck.Workbook.Worksheets.Add("PivotWithCaptionFilter"); + + //Create a new pivot table with a new cache. + var pivotTable4 = wsPivot4.PivotTables.Add(wsPivot4.Cells["A3"], dataRange, "WithCaptionFilter"); + var rowField1 = pivotTable4.RowFields.Add(pivotTable4.Fields["Name"]); + + //Add the Caption filter (Label filter in Excel) to the pivot table. + rowField1.Filters.AddCaptionFilter(ePivotTableCaptionFilterType.CaptionNotBeginsWith, "C"); + + //Add a rowfield + var rowField2 = pivotTable4.RowFields.Add(pivotTable4.Fields["OrderDate"]); + + //Add a date value filter to the pivot table. + rowField2.Filters.AddDateValueFilter(ePivotTableDateValueFilterType.DateBetween, new DateTime(2017,8,1), new DateTime(2017, 8, 31)); + + //Filters will apply on top of any selection made directly on the items. + rowField2.Items.Refresh(); + rowField2.Items[8].Hidden = true; + + //Number formats can be set directly on fields as well as on datafields... + pivotTable4.Fields["OrderDate"].Format = "yyyy-MM-dd hh:mm:ss"; + pivotTable4.Fields["OrderValue"].Format = "#,##0"; + pivotTable4.Fields["Tax"].Format = "#,##0"; + pivotTable4.Fields["Freight"].Format = "#,##0"; + + //Add the data fields and format them + pivotTable4.DataFields.Add(pivotTable4.Fields["OrderValue"]); + pivotTable4.DataFields.Add(pivotTable4.Fields["Tax"]); + pivotTable4.DataFields.Add(pivotTable4.Fields["Freight"]); + + //We want the datafields to appear in columns + pivotTable4.DataOnRows = false; + return pivotTable4; + } private static List GetDataFromSQL(string connectionStr) { var ret = new List(); diff --git a/24-Slicers/Readme.md b/24-Slicers/Readme.md new file mode 100644 index 0000000..2775e3e --- /dev/null +++ b/24-Slicers/Readme.md @@ -0,0 +1,9 @@ +# 24 - Slicers +These samples demonstrates slicer functionality of EPPlus. +A slicer is a drawing object that reflects the filter for various data objects. +EPPlus implement support for table and pivot table slicers. + +### [SlicerSample.cs](SlicerSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/24-Slicers/SlicerSample.cs b/24-Slicers/SlicerSample.cs new file mode 100644 index 0000000..e0fd837 --- /dev/null +++ b/24-Slicers/SlicerSample.cs @@ -0,0 +1,161 @@ +using OfficeOpenXml; +using OfficeOpenXml.Filter; +using System; +using System.Data.SQLite; + +namespace EPPlusSamples +{ + public class SlicerSample + { + public static void Run(string connectionString) + { + using (var p = new ExcelPackage()) + { + //A sample with a table and several slicers. + TableSlicerSample(p, connectionString); + + //Creates the source data for the pivot tables in a separate sheet. + CreatePivotTableSourceWorksheet(p, connectionString); + + //Create a pivot table with a slicer connected to one field. + PivotTableSlicerSample(p); + PivotTableOneSlicerToMultiplePivotTables(p); + + p.SaveAs(FileOutputUtil.GetFileInfo("24-Slicers.xlsx")); + } + } + + private static void PivotTableOneSlicerToMultiplePivotTables(ExcelPackage p) + { + var wsSource = p.Workbook.Worksheets["PivotTableSourceData"]; + var wsPivot = p.Workbook.Worksheets.Add("OneSlicerToTwoPivotTables"); + + var pivotTable1 = wsPivot.PivotTables.Add(wsPivot.Cells["D15"], wsSource.Cells[wsSource.Dimension.Address], "PivotTable1"); + pivotTable1.RowFields.Add(pivotTable1.Fields["Company Name"]); + pivotTable1.DataFields.Add(pivotTable1.Fields["Order Value"]); + pivotTable1.DataFields.Add(pivotTable1.Fields["Tax"]); + pivotTable1.DataFields.Add(pivotTable1.Fields["Freight"]); + pivotTable1.DataOnRows = false; + + //To connect a slicer to multiple pivot tables the tables need to use the same pivot table cache, so we use pivotTable1's cache as source to pivotTable2... + var pivotTable2 = wsPivot.PivotTables.Add(wsPivot.Cells["H15"], pivotTable1.CacheDefinition, "PivotTable2"); + pivotTable2.RowFields.Add(pivotTable2.Fields["Country"]); + pivotTable2.DataFields.Add(pivotTable2.Fields["Order Value"]); + pivotTable2.DataFields.Add(pivotTable2.Fields["Tax"]); + pivotTable2.DataFields.Add(pivotTable2.Fields["Freight"]); + pivotTable2.DataOnRows = false; + + var slicer1 = pivotTable1.Fields["Country"].AddSlicer(); + slicer1.Caption = "Country - Both"; + + //Now add the second pivot table to the slicer cache. This require that the pivot tables share the same cache. + slicer1.Cache.PivotTables.Add(pivotTable2); + slicer1.SetPosition(0, 0, 0, 0); + slicer1.Style = eSlicerStyle.Light4; + + var slicer2 = pivotTable1.Fields["Company Name"].AddSlicer(); + slicer2.Caption = "Company Name - PivotTable1"; + slicer2.SetPosition(0, 0, 3, 0); + slicer2.To.Column = 7; + + var slicer3 = pivotTable2.Fields["Order date"].AddSlicer(); + slicer3.Caption = "Order date - PivotTable2"; + slicer3.SetPosition(0, 0, 7, 0); + slicer3.To.Column = 11; + } + private static void TableSlicerSample(ExcelPackage p, string connectionString) + { + var worksheet1 = p.Workbook.Worksheets.Add("TableSlicer"); + var worksheet2 = p.Workbook.Worksheets.Add("TableSlicerToOtherWorksheet"); + // Lets connect to the sample database for some data + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName as 'Company Name', [Name] as Name, Email as 'E-Mail', c.Country as Country, orderdate as 'Order Date', (ordervalue) as 'Order Value',tax as Tax, freight As Freight, currency As Currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + using (var sqlReader = sqlCmd.ExecuteReader()) + { + var range = worksheet1.Cells["A1"].LoadFromDataReader(sqlReader, true, "tblSalesData", OfficeOpenXml.Table.TableStyles.Medium6); + var tbl = worksheet1.Tables.GetFromRange(range); + range.Offset(1, 4, range.Rows - 1, 1).Style.Numberformat.Format = "yyyy-MM-dd"; + range.Offset(1, 5, range.Rows - 1, 3).Style.Numberformat.Format = "#,##0"; + + //You can either add a slicer via the table column... + var slicer1 = tbl.Columns[0].AddSlicer(); + //Filter values are compared to the Text property of the cell. + slicer1.FilterValues.Add("Barton-Veum"); + slicer1.FilterValues.Add("Christiansen LLC"); + slicer1.SetPosition(2, 0, 10, 0); + + //... or you can add it via the drawings collection. + var slicer2 = worksheet1.Drawings.AddTableSlicer(tbl.Columns["Country"]); + slicer2.SetPosition(2, 0, 13, 0); + + //A slicer also supports date groups... + var slicer3 = tbl.Columns["Order Date"].AddSlicer(); + slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 6)); + slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 7)); + slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 8)); + slicer3.SetPosition(2, 0, 16, 0); + + //... You can also add a slicer to another worksheet, if you use the drawings collection... + var slicer4 = worksheet2.Drawings.AddTableSlicer(tbl.Columns["E-Mail"]); + slicer4.Caption = "E-Mail - TableSlicer Worksheet"; + slicer4.Description = "This slicer reference a table in another worksheet."; + slicer4.SetPosition(1, 0, 1, 0); + slicer4.To.Column = 7; //Set the end position anchor to column H, to make the slicer wider. + } + } + sqlConn.Close(); + } + worksheet1.Cells.AutoFitColumns(); + } + private static void PivotTableSlicerSample(ExcelPackage p) + { + var wsSource = p.Workbook.Worksheets["PivotTableSourceData"]; + var wsPivot = p.Workbook.Worksheets.Add("PivotTableSlicer"); + + var pivotTable = wsPivot.PivotTables.Add(wsPivot.Cells["A1"], wsSource.Cells[wsSource.Dimension.Address], "PivotTable1"); + pivotTable.RowFields.Add(pivotTable.Fields["Company Name"]); + pivotTable.DataFields.Add(pivotTable.Fields["Order Value"]); + pivotTable.DataFields.Add(pivotTable.Fields["Tax"]); + pivotTable.DataFields.Add(pivotTable.Fields["Freight"]); + pivotTable.DataOnRows = false; + + var slicer1 = pivotTable.Fields["Name"].AddSlicer(); + slicer1.SetPosition(0, 0, 10, 0); + slicer1.SetSize(400, 208); + slicer1.Style = eSlicerStyle.Light4; + slicer1.Cache.Data.Items.GetByValue("Brown Kutch").Hidden=true; + slicer1.Cache.Data.Items.GetByValue("Tierra Ratke").Hidden = true; + slicer1.Cache.Data.Items.GetByValue("Jamarcus Schimmel").Hidden = true; + + //Add a column with two columns and start showing the item 3. + slicer1.ColumnCount = 2; + slicer1.StartItem = 3; + slicer1.Cache.Data.CrossFilter = eCrossFilter.ShowItemsWithNoData; + slicer1.Cache.Data.SortOrder = eSortOrder.Descending; + } + private static void CreatePivotTableSourceWorksheet(ExcelPackage p, string connectionString) + { + var wsSource = p.Workbook.Worksheets.Add("PivotTableSourceData"); + //Lets connect to the sample database for some data + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName as 'Company Name', [Name] as Name, Email as 'EMail', c.Country as Country, orderdate as 'Order Date', ordervalue as 'Order Value',tax as Tax, freight As Freight, currency As Currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + using (var sqlReader = sqlCmd.ExecuteReader()) + { + var range = wsSource.Cells["A1"].LoadFromDataReader(sqlReader, true); + range.Offset(0, 0, 1, range.Columns).Style.Font.Bold = true; + range.Offset(1, 4, range.Rows - 1, 1).Style.Numberformat.Format = "yyyy-MM-dd hh:mm"; + range.Offset(1, 5, range.Rows - 1, 3).Style.Numberformat.Format = "#,##0"; + } + } + sqlConn.Close(); + } + wsSource.Cells.AutoFitColumns(); + } + } +} diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index bb23578..48f101d 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,14 +42,17 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.2.1.259-20200818-develop\lib\net45\EPPlus.dll + + packages\EPPlus.5.4.0\lib\net45\EPPlus.dll packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll + @@ -113,6 +116,7 @@ + @@ -147,6 +151,7 @@ + PreserveNewest diff --git a/Sample_Main.cs b/Sample_Main.cs index a56f4fc..cea0b9c 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -22,13 +22,13 @@ Date Author Change using EPPlusSamples.FormulaCalculation; using EPPlusSamples.FXReportFromDatabase; using EPPlusSamples.LoadDataFromCsvFilesIntoTables; -using EPPlusSamples.LoadingDataWithTables; using EPPlusSamples.OpenWorkbookAddDataAndChart; using EPPlusSamples.PerformanceAndProtection; using EPPlusSamples.PivotTables; using EPPlusSamples.SalesReport; using EPPlusSamples.Sparklines; using EPPlusSamples.Comments; +using EPPlusSamples.LoadingData; namespace EPPlusSamples { @@ -202,6 +202,12 @@ await ChartsAndThemesSample.RunAsync(connectionStr, Console.WriteLine("Running sample 23-Comments/Notes and Threaded Comments"); CommentsSample.Run(); Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); + + //Sample 24 - Table slicers and Pivot table slicers + Console.WriteLine("Running sample 24-Table and Pivot table slicers"); + SlicerSample.Run(connectionStr); + Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index e904267..15a7550 100644 --- a/packages.config +++ b/packages.config @@ -1,8 +1,9 @@  - + + From 3ed29baef384e67db3284bac2abf60fb1e9b71a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Thu, 8 Oct 2020 16:21:14 +0200 Subject: [PATCH 02/18] Version 5.4 --- 18-PivotTables/PivotTablesSample.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/18-PivotTables/PivotTablesSample.cs b/18-PivotTables/PivotTablesSample.cs index 7d1051f..46b9add 100644 --- a/18-PivotTables/PivotTablesSample.cs +++ b/18-PivotTables/PivotTablesSample.cs @@ -214,7 +214,7 @@ private static ExcelPivotTable CreatePivotTableWithACalculatedField(ExcelPackage pivotTable4.RowFields.Add(pivotTable4.Fields["CompanyName"]); pivotTable4.RowFields.Add(pivotTable4.Fields["OrderDate"]); - //Be carfull with formulas as they are not validated and can cause the pivot table to become corrupt. + //Be careful with formulas as they can cause the pivot table to become corrupt if they are entered invalidly. var calcField = pivotTable4.Fields.AddCalculatedField("Total", "'OrderValue'+'Tax'+'Freight'"); calcField.Format = "#,##0"; From 5040bcd84b1363535baf4562a577bc2a6db0393c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Fri, 23 Oct 2020 13:55:08 +0200 Subject: [PATCH 03/18] Update Readme.md --- Readme.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 837c7eb..2b0c0a3 100644 --- a/Readme.md +++ b/Readme.md @@ -9,7 +9,7 @@ The solution can be opened in Visual Studio for Windows. |01|[Getting started](/01-GettingStarted/)|Basic usage of EPPlus: create a workbook, fill with data and some basic styling| |02|[Read workbook](/02-ReadWorkbook/)|Read data from a workbook| |03|[Async/Await](/03-UsingAsyncAwait/)|Using async/await methods for loading and saving data| -|04|[Loading data](/04-LoadingDataWithTables/)|Load data into a worksheet from various types of objects and create a table. It also demonstrates the Autofit columns feature.| +|04|[Loading data](/04-LoadingData/)|Load data into a worksheet from various types of objects and create a table. It also demonstrates the Autofit columns feature.| |05|[Import and Export csv files and create charts](/05-ImportAndExportCsvFiles/)|This sample shows how to load and save CSV files using the LoadFromText and SaveToText methods, how to use tables and how to use charts with more than one charttype and secondary axis.| |06|[Calculate formulas](/06-FormulaCalculation/)|How to calculate formulas and add custom/missing functions in a workbook| |07|[Open workbook and add data/chart](/07-OpenWorkbookAddDataAndChart/)|Opens an existing workbook, adds some data and a pie chart.| @@ -18,7 +18,7 @@ The solution can be opened in Visual Studio for Windows. |10|[Read data using Linq](/10-ReadDataUsingLinq/)|This sample shows how to use Linq with the Cells collection to read sample 9.| |11|[Conditional formatting](/11-ConditionalFormatting/)|Demonstrates conditional formatting.| |12|[Data validation](/12-DataValidation/)|How to add various types of data validation to a workbook and read existing validations.| -|13|[Filters](/13-Filter/)|How to apply filters in a worksheet or a table| +|13|[Filters](/13-Filter/)|How to apply filters in a worksheet, table or a pivot table| |14|[Shapes & Images](/14-ShapesAndImages/)|Shows how to add shapes and format them in different ways. |15|[Chart Styling & Themes ](/15-ChartsAndThemes/)|Load a theme and create various charts and style them. |16|[Sparklines](/16-Sparklines/)|Demonstrates sparklines functionality.| @@ -27,6 +27,9 @@ The solution can be opened in Visual Studio for Windows. |19|[Encryption and protection](/19-EncryptionAndProtection/)|This sample produces a quiz, where the template workbook is encrypted and password protected.| |20|[Create filesystem report](/20-CreateFileSystemReport/)|Demonstrates usage of styling, printer settings, rich text, pie-, doughnut- and bar-charts, freeze panes| |21|[VBA - Visual Basic for Applications](/21-VBA/)|Demonstrates EPPlus support for VBA, includes a battleship game| +|22|[Ignore errors](/22-IgnoreErrors/)|Various samples on how to ignore error on cells.| +|23|[Comments](/23-Comments/)|Sample showing how to add notes and threaded comments.| +|24|[Slicers](/24-Slicers/)|Sample showing how to add Pivot Table slicers and Tabel slicers ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. From 47a7234f159ecc0a73522bfda8ecac0f02d0559a Mon Sep 17 00:00:00 2001 From: Mats Alm <897655+swmal@users.noreply.github.com> Date: Thu, 5 Nov 2020 23:58:11 +0100 Subject: [PATCH 04/18] Added sample for ToDataTable --- .../DataTableSample.cs | 127 ++++++++++++++++++ 25-ImportAndExportDataTable/readme.md | 1 + EPPlus.Sample.NET.csproj | 6 +- Readme.md | 3 +- Sample_Main.cs | 6 + packages.config | 2 +- 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 25-ImportAndExportDataTable/DataTableSample.cs create mode 100644 25-ImportAndExportDataTable/readme.md diff --git a/25-ImportAndExportDataTable/DataTableSample.cs b/25-ImportAndExportDataTable/DataTableSample.cs new file mode 100644 index 0000000..31eeb24 --- /dev/null +++ b/25-ImportAndExportDataTable/DataTableSample.cs @@ -0,0 +1,127 @@ +using OfficeOpenXml; +using OfficeOpenXml.Export.ToDataTable; +using OfficeOpenXml.Table; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.Text; + +namespace EPPlusSamples +{ + public class DataTableSample + { + public static void Run(string connectionString) + { + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName as 'Company Name', [Name] as Name, Email as 'E-Mail', c.Country as Country, orderdate as 'Order Date', (ordervalue) as 'Order Value',tax as Tax, freight As Freight, currency As Currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + var reader = sqlCmd.ExecuteReader(); + var dataTable = new DataTable(); + dataTable.Load(reader); + + // Create a workbook + using (var package = new ExcelPackage()) + { + var sheet = package.Workbook.Worksheets.Add("DataTable Samples"); + + /***** Load from DataTable ***/ + + // Import the DataTable using LoadFromDataTable + sheet.Cells["A1"].LoadFromDataTable(dataTable, true, TableStyles.Dark11); + + // Now let's export this data back to a DataTable. We know that the data is in a + // table, so we are using the ExcelTables interface to get the range + var dt1 = sheet.Tables[0].ToDataTable(); + PrintDataTable(dt1); + + + /***** Export to DataTable ***/ + + // Export a specific range instead of the entire table + // and use the config action to set the table name + var dt2 = sheet.Cells["A1:F11"].ToDataTable(o => o.DataTableName = "dt2"); + PrintDataTable(dt2); + + // Configure some properties on how the table is generated + var dt3 = sheet.Cells["A1:F11"].ToDataTable(c => + { + // set name and namespace + c.DataTableName = "MyDataTable"; + c.DataTableNamespace = "MyNamespace"; + // Removes spaces in column names when read from the first row + c.ColumnNameParsingStrategy = NameParsingStrategy.RemoveSpace; + // Rename the third column from E-Mail to EmailAddress + c.Mappings.Add(2, "EmailAddress"); + // Ensure that the OrderDate column is casted to DateTime (in Excel it can sometimes be stored as a double/OADate) + c.Mappings.Add(4, "OrderDate", typeof(DateTime)); + // Change the OrderValue to a string + c.Mappings.Add(5, "OrderValue", typeof(string), false, cellVal => "Val: " + cellVal.ToString()); + // Skip the first 2 rows + c.SkipNumberOfRowsStart = 2; + // Skip the last 100 rows + c.SkipNumberOfRowsEnd = 4; + + }); + PrintDataTable(dt3); + + // Export to existing DataTable + + // Create the DataTable + var dataTable2 = new DataTable("myDataTable", "myNamespace"); + dataTable2.Columns.Add("Company Name", typeof(string)); + dataTable2.Columns.Add("E-Mail"); + sheet.Cells["A1:F11"].ToDataTable(o => o.FirstRowIsColumnNames = true, dataTable2); + PrintDataTable(dataTable2); + + // Create the DataTable, use mappings if names of columns/range headers differ + var dataTable3 = new DataTable("myDataTableWithMappings", "myNamespace"); + var col1 = dataTable3.Columns.Add("CompanyName"); + var col2 = dataTable3.Columns.Add("Email"); + sheet.Cells["A1:F11"].ToDataTable(o => + { + o.FirstRowIsColumnNames = true; + o.Mappings.Add(0, col1); + o.Mappings.Add(1, col2); + } + , dataTable3); + PrintDataTable(dataTable3); + + } + + } + } + } + + private static void PrintDataTable(DataTable table) + { + Console.WriteLine(); + Console.WriteLine("DATATABLE name=" + table.TableName); + var cols = new StringBuilder(); + foreach (var col in table.Columns) + { + cols.AppendFormat("'{0}' ", ((DataColumn)col).ColumnName); + } + Console.WriteLine("Columns:"); + Console.WriteLine(cols.ToString()); + Console.WriteLine(); + + Console.WriteLine("First 10 rows:"); + for (var r = 0; r < table.Rows.Count && r < 10; r++) + { + for (var c = 0; c < table.Columns.Count; c++) + { + var col = table.Columns[c] as DataColumn; + var row = table.Rows[r] as DataRow; + var val = col.DataType == typeof(string) ? "'" + row[col.ColumnName] + "'" : row[col.ColumnName]; + + + Console.Write(c == 0 ? val : ", " + val); + } + Console.WriteLine(); + } + } + } +} diff --git a/25-ImportAndExportDataTable/readme.md b/25-ImportAndExportDataTable/readme.md new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/25-ImportAndExportDataTable/readme.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 48f101d..13a0ece 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,8 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.4.0\lib\net45\EPPlus.dll + + packages\EPPlus.5.4.1\lib\net45\EPPlus.dll packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll @@ -117,6 +117,7 @@ + @@ -152,6 +153,7 @@ + PreserveNewest diff --git a/Readme.md b/Readme.md index 2b0c0a3..979c4b3 100644 --- a/Readme.md +++ b/Readme.md @@ -29,7 +29,8 @@ The solution can be opened in Visual Studio for Windows. |21|[VBA - Visual Basic for Applications](/21-VBA/)|Demonstrates EPPlus support for VBA, includes a battleship game| |22|[Ignore errors](/22-IgnoreErrors/)|Various samples on how to ignore error on cells.| |23|[Comments](/23-Comments/)|Sample showing how to add notes and threaded comments.| -|24|[Slicers](/24-Slicers/)|Sample showing how to add Pivot Table slicers and Tabel slicers +|24|[Slicers](/24-Slicers/)|Sample showing how to add Pivot Table slicers and Tabel +|25|[Export to/from DataTable](/25-ImportAndExportDataTable)|Sample showing import/export rangedata with System.Data.DataTable ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. diff --git a/Sample_Main.cs b/Sample_Main.cs index cea0b9c..7602d7f 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -208,6 +208,12 @@ await ChartsAndThemesSample.RunAsync(connectionStr, SlicerSample.Run(connectionStr); Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); Console.WriteLine(); + + //Sample 25 - Import and Export DataTable + Console.WriteLine("Running sample 25 - Import and Export DataTable"); + DataTableSample.Run(connectionStr); + Console.WriteLine("Sample 25 finished."); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index 15a7550..f839f51 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - + From f638644faa732cf8d18b8472cc938cf4e96ef6ee Mon Sep 17 00:00:00 2001 From: Mats Alm <897655+swmal@users.noreply.github.com> Date: Fri, 6 Nov 2020 00:00:53 +0100 Subject: [PATCH 05/18] Fixed readme for sample 25 --- 25-ImportAndExportDataTable/readme.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/25-ImportAndExportDataTable/readme.md b/25-ImportAndExportDataTable/readme.md index 5f28270..44e8697 100644 --- a/25-ImportAndExportDataTable/readme.md +++ b/25-ImportAndExportDataTable/readme.md @@ -1 +1,7 @@ - \ No newline at end of file +# 25 - Import/export with DataTable +These samples demonstrates how to import and export data to/from a range to/from a DataTable. + +### [DataTableSample.cs](DataTableSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file From 8dae5d6fd98b3b087c142a8f02249ef328dc5690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Fri, 18 Dec 2020 16:12:46 +0100 Subject: [PATCH 06/18] EPPlus 5.5.0 --- ...LoadingDataFromCollectionWithAttributes.cs | 76 +++++++++ 04-LoadingData/Readme.md | 6 + .../DataTableSample.cs | 127 ++++++++++++++ 25-ImportAndExportDataTable/Readme.md | 7 + 26-FormControls/FormControlsSample.cs | 157 ++++++++++++++++++ 26-FormControls/Readme.md | 8 + EPPlus.Sample.NET.csproj | 13 +- Readme.md | 5 + Sample_Main.cs | 14 +- packages.config | 3 +- 10 files changed, 412 insertions(+), 4 deletions(-) create mode 100644 04-LoadingData/LoadingDataFromCollectionWithAttributes.cs create mode 100644 25-ImportAndExportDataTable/DataTableSample.cs create mode 100644 25-ImportAndExportDataTable/Readme.md create mode 100644 26-FormControls/FormControlsSample.cs create mode 100644 26-FormControls/Readme.md diff --git a/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs new file mode 100644 index 0000000..cffbc0b --- /dev/null +++ b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs @@ -0,0 +1,76 @@ +using OfficeOpenXml; +using OfficeOpenXml.Attributes; +using OfficeOpenXml.Table; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EPPlusSamples.LoadingData +{ + [EpplusTable(TableStyle = TableStyles.Dark1, PrintHeaders = true, AutofitColumns = true, AutoCalculate = false, ShowTotal = true, ShowFirstColumn = true)] + [ + EpplusFormulaTableColumn(Order = 6, NumberFormat = "€#,##0.00", Header = "Tax amount", FormulaR1C1 = "RC[-2] * RC[-1]", TotalsRowFunction = RowFunctions.Sum, TotalsRowNumberFormat = "€#,##0.00"), + EpplusFormulaTableColumn(Order = 7, NumberFormat = "€#,##0.00", Header = "Net salary", Formula = "E2-G2", TotalsRowFunction = RowFunctions.Sum, TotalsRowNumberFormat = "€#,##0.00") + ] + internal class Actor + { + [EpplusIgnore] + public int Id { get; set; } + + [EpplusTableColumn(Order = 3)] + public string LastName { get; set; } + [EpplusTableColumn(Order = 1, Header = "First name")] + public string FirstName { get; set; } + [EpplusTableColumn(Order = 2)] + public string MiddleName { get; set; } + + [EpplusTableColumn(Order = 0, NumberFormat = "yyyy-MM-dd", TotalsRowLabel = "Total")] + public DateTime Birthdate { get; set; } + + [EpplusTableColumn(Order = 4, NumberFormat = "€#,##0.00", TotalsRowFunction = RowFunctions.Sum, TotalsRowNumberFormat = "€#,##0.00")] + public double Salary { get; set; } + + [EpplusTableColumn(Order = 5, NumberFormat = "0%", TotalsRowFormula = "Table1[[#Totals],[Tax amount]]/Table1[[#Totals],[Salary]]", TotalsRowNumberFormat = "0 %")] + public double Tax { get; set; } + } + + [EpplusTable(TableStyle = TableStyles.Medium1, PrintHeaders = true, AutofitColumns = true, AutoCalculate = true, ShowLastColumn = true)] + internal class Actor2 : Actor + { + + } + + public static class LoadingDataFromCollectionWithAttributes + { + public static void Run() + { + // sample data + var actors = new List + { + new Actor{ Salary = 256.24, Tax = 0.21, FirstName = "John", MiddleName = "Bernhard", LastName = "Doe", Birthdate = new DateTime(1950, 3, 15) }, + new Actor{ Salary = 278.55, Tax = 0.23, FirstName = "Sven", MiddleName = "Bertil", LastName = "Svensson", Birthdate = new DateTime(1962, 6, 10)}, + new Actor{ Salary = 315.34, Tax = 0.28, FirstName = "Lisa", MiddleName = "Maria", LastName = "Gonzales", Birthdate = new DateTime(1971, 10, 2)} + }; + + var subclassActors = new List + { + new Actor2{ Salary = 256.24, Tax = 0.21, FirstName = "John", MiddleName = "Bernhard", LastName = "Doe", Birthdate = new DateTime(1950, 3, 15) }, + new Actor2{ Salary = 278.55, Tax = 0.23, FirstName = "Sven", MiddleName = "Bertil", LastName = "Svensson", Birthdate = new DateTime(1962, 6, 10)}, + new Actor2{ Salary = 315.34, Tax = 0.28, FirstName = "Lisa", MiddleName = "Maria", LastName = "Gonzales", Birthdate = new DateTime(1971, 10, 2)} + }; + + using (var package = new ExcelPackage(FileOutputUtil.GetFileInfo("04-LoadFromCollectionAttributes.xlsx"))) + { + // using the Actor class above + var sheet = package.Workbook.Worksheets.Add("Actors"); + sheet.Cells["A1"].LoadFromCollection(actors); + + // using a subclass where we have overridden the EpplusTableAttribute (different TableStyle and highlight last column instead of the first). + var subclassSheet = package.Workbook.Worksheets.Add("Using subclass with attributes"); + subclassSheet.Cells["A1"].LoadFromCollection(subclassActors); + + package.Save(); + } + } + } +} diff --git a/04-LoadingData/Readme.md b/04-LoadingData/Readme.md index 2e88fdb..0a67c23 100644 --- a/04-LoadingData/Readme.md +++ b/04-LoadingData/Readme.md @@ -7,6 +7,12 @@ Demonstrates how to load data into a worksheet from the following object types: - Anonymous classes - POCO instances (strongly typed classes) - DataTable +### [LoadingDataWithDynamicObjects.cs](LoadingDataWithDynamicObjects.cs) +Demonstrates how to load data into a worksheet from the following object types: + +- dynamic/ExpandoObject's + +It also show how to load json data from a file into a worksheet. --- [Back to overview](/Readme.md) diff --git a/25-ImportAndExportDataTable/DataTableSample.cs b/25-ImportAndExportDataTable/DataTableSample.cs new file mode 100644 index 0000000..43bb6a2 --- /dev/null +++ b/25-ImportAndExportDataTable/DataTableSample.cs @@ -0,0 +1,127 @@ +using OfficeOpenXml; +using OfficeOpenXml.Export.ToDataTable; +using OfficeOpenXml.Table; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SQLite; +using System.Text; + +namespace EPPlusSamples +{ + public class DataTableSample + { + public static void Run(string connectionString) + { + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName as 'Company Name', [Name] as Name, Email as 'E-Mail', c.Country as Country, orderdate as 'Order Date', (ordervalue) as 'Order Value',tax as Tax, freight As Freight, currency As Currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + var reader = sqlCmd.ExecuteReader(); + var dataTable = new DataTable(); + dataTable.Load(reader); + + // Create a workbook + using(var package = new ExcelPackage()) + { + var sheet = package.Workbook.Worksheets.Add("DataTable Samples"); + + /***** Load from DataTable ***/ + + // Import the DataTable using LoadFromDataTable + sheet.Cells["A1"].LoadFromDataTable(dataTable, true, TableStyles.Dark11); + + // Now let's export this data back to a DataTable. We know that the data is in a + // table, so we are using the ExcelTables interface to get the range + var dt1 = sheet.Tables[0].ToDataTable(); + PrintDataTable(dt1); + + + /***** Export to DataTable ***/ + + // Export a specific range instead of the entire table + // and use the config action to set the table name + var dt2 = sheet.Cells["A1:F11"].ToDataTable(o => o.DataTableName = "dt2"); + PrintDataTable(dt2); + + // Configure some properties on how the table is generated + var dt3 = sheet.Cells["A1:F11"].ToDataTable(c => + { + // set name and namespace + c.DataTableName = "MyDataTable"; + c.DataTableNamespace = "MyNamespace"; + // Removes spaces in column names when read from the first row + c.ColumnNameParsingStrategy = NameParsingStrategy.RemoveSpace; + // Rename the third column from E-Mail to EmailAddress + c.Mappings.Add(2, "EmailAddress"); + // Ensure that the OrderDate column is casted to DateTime (in Excel it can sometimes be stored as a double/OADate) + c.Mappings.Add(4, "OrderDate", typeof(DateTime)); + // Change the OrderValue to a string + c.Mappings.Add(5, "OrderValue", typeof(string), false, cellVal => "Val: " + cellVal.ToString()); + // Skip the first 2 rows + c.SkipNumberOfRowsStart = 2; + // Skip the last 100 rows + c.SkipNumberOfRowsEnd = 4; + + }); + PrintDataTable(dt3); + + // Export to existing DataTable + + // Create the DataTable + var dataTable2 = new DataTable("myDataTable", "myNamespace"); + dataTable2.Columns.Add("Company Name", typeof(string)); + dataTable2.Columns.Add("E-Mail"); + sheet.Cells["A1:F11"].ToDataTable(o => o.FirstRowIsColumnNames = true, dataTable2); + PrintDataTable(dataTable2); + + // Create the DataTable, use mappings if names of columns/range headers differ + var dataTable3 = new DataTable("myDataTableWithMappings", "myNamespace"); + var col1 = dataTable3.Columns.Add("CompanyName"); + var col2 = dataTable3.Columns.Add("Email"); + sheet.Cells["A1:F11"].ToDataTable(o => + { + o.FirstRowIsColumnNames = true; + o.Mappings.Add(0, col1); + o.Mappings.Add(1, col2); + } + , dataTable3); + PrintDataTable(dataTable3); + + } + + } + } + } + + private static void PrintDataTable(DataTable table) + { + Console.WriteLine(); + Console.WriteLine("DATATABLE name=" + table.TableName); + var cols = new StringBuilder(); + foreach (var col in table.Columns) + { + cols.AppendFormat("'{0}' ", ((DataColumn)col).ColumnName); + } + Console.WriteLine("Columns:"); + Console.WriteLine(cols.ToString()); + Console.WriteLine(); + + Console.WriteLine("First 10 rows:"); + for(var r = 0; r < table.Rows.Count && r < 10; r++) + { + for(var c = 0; c < table.Columns.Count; c++) + { + var col = table.Columns[c] as DataColumn; + var row = table.Rows[r] as DataRow; + var val = col.DataType == typeof(string) ? "'" + row[col.ColumnName] + "'" : row[col.ColumnName]; + + + Console.Write(c == 0 ? val : ", " + val); + } + Console.WriteLine(); + } + } + } +} diff --git a/25-ImportAndExportDataTable/Readme.md b/25-ImportAndExportDataTable/Readme.md new file mode 100644 index 0000000..44e8697 --- /dev/null +++ b/25-ImportAndExportDataTable/Readme.md @@ -0,0 +1,7 @@ +# 25 - Import/export with DataTable +These samples demonstrates how to import and export data to/from a range to/from a DataTable. + +### [DataTableSample.cs](DataTableSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/26-FormControls/FormControlsSample.cs b/26-FormControls/FormControlsSample.cs new file mode 100644 index 0000000..d0b8cc2 --- /dev/null +++ b/26-FormControls/FormControlsSample.cs @@ -0,0 +1,157 @@ +using OfficeOpenXml; +using OfficeOpenXml.Drawing; +using OfficeOpenXml.Style; +using System; +using System.Drawing; +using System.Text; + +namespace EPPlusSamples +{ + public class FormControlsSample + { + public static void Run() + { + using (var package = new ExcelPackage()) + { + //First create the sheet containing the data for the check box and the list box. + var dataSheet = CreateDataSheet(package); + + //Create the form-sheet and set headers and som basic properties. + ExcelWorksheet formSheet = CreateFormSheet(package); + + //Add texts and format the text fields style + formSheet.Cells["A3"].Value = "Name"; + formSheet.Cells["A4"].Value = "Gender"; + formSheet.Cells["B3,B5,B11"].Style.Border.BorderAround(ExcelBorderStyle.Dotted); + formSheet.Cells["B3,B5,B11"].Style.Fill.SetBackground(eThemeSchemeColor.Background1); + + //Controls are added via the worksheets drawings collection. + //Each type has its typed method returning the specific control class. + //Optionally you can use the AddControl method specifying the control type via the eControlType enum + var dropDown = formSheet.Drawings.AddDropDownControl("DropDown1"); + dropDown.InputRange = dataSheet.Cells["A1:A2"]; //Linkes to the range of items + dropDown.LinkedCell = formSheet.Cells["G4"]; //The cell where the selected index is updated. + dropDown.SetPosition(3, 1, 1, 0); + dropDown.SetSize(451, 31); + + formSheet.Cells["A5"].Value = "Number of guests"; + + //Add a spin button for the number of guests cell + var spinnButton = formSheet.Drawings.AddSpinButtonControl("SpinButton1"); + spinnButton.SetPosition(4, 0, 2, 1); + spinnButton.SetSize(30, 35); + spinnButton.Value = 0; + spinnButton.Increment = 1; + spinnButton.MinValue = 0; + spinnButton.MaxValue = 3; + spinnButton.LinkedCell = formSheet.Cells["B5"]; + spinnButton.Value = 1; + + //Add a group box and four option buttons to select room type + var grpBox = formSheet.Drawings.AddGroupBoxControl("GroupBox 1"); + grpBox.Text = "Room types"; + grpBox.SetPosition(5, 8, 1, 1); + grpBox.SetSize(150, 150); + + var r1 = formSheet.Drawings.AddRadioButtonControl("OptionSingleRoom"); + r1.Text = "Single Room"; + r1.FirstButton = true; + r1.LinkedCell = formSheet.Cells["G7"]; + r1.SetPosition(5, 15, 1, 5); + + var r2 = formSheet.Drawings.AddRadioButtonControl("OptionDoubleRoom"); + r2.Text = "Double Room"; + r2.LinkedCell = formSheet.Cells["G7"]; + r2.SetPosition(6, 15, 1, 5); + r2.Checked = true; + + var r3 = formSheet.Drawings.AddRadioButtonControl("OptionSuperiorRoom"); + r3.Text = "Superior"; + r3.LinkedCell = formSheet.Cells["G7"]; + r3.SetPosition(7, 15, 1, 5); + + var r4 = formSheet.Drawings.AddRadioButtonControl("OptionSuite"); + r4.Text = "Suite"; + r4.LinkedCell = formSheet.Cells["G7"]; + r4.SetPosition(8, 15, 1, 5); + + //Group the groupbox together with the radio buttons, so they act as one unit. + //You can group drawings via the Group method on one of the drawings, here using the group box... + var grp = grpBox.Group(r1, r2, r3); //This will group the groupbox and three of the radio buttons. You would normally include r4 here as well, but we add it in the next statement to demonstrate how group shapes work. + //...Or add them to a group drawing returned by the Group method. + grp.Drawings.Add(r4); //This will add the fourth radio button to the group + + //Add a scroll bar to control the number of nights + formSheet.Cells["A11"].Value = "Number of nights"; + var scrollBar = formSheet.Drawings.AddScrollBarControl("Scrollbar1"); + scrollBar.Horizontal = true; //We want a horizontal scrollbar + scrollBar.SetPosition(10, 1, 2, 1); + scrollBar.SetSize(200, 30); + scrollBar.LinkedCell = formSheet.Cells["B11"]; + scrollBar.MinValue = 1; + scrollBar.MaxValue = 365; + scrollBar.Increment = 1; + scrollBar.Page = 7; //How much a page click should increase. + scrollBar.Value = 1; + + //Add a listbox and connect it to the input range in the data sheet + formSheet.Cells["A12"].Value = "Requests"; + var listBox = formSheet.Drawings.AddListBoxControl("Listbox1"); + listBox.InputRange = dataSheet.Cells["B1:B3"]; + listBox.LinkedCell = formSheet.Cells["G12"]; + listBox.SetPosition(11, 5, 1, 0); + listBox.SetSize(200, 100); + + //Last, add a button and connect it to a macro appending the data to a text file. + var button = formSheet.Drawings.AddButtonControl("ExportButton"); + button.Text = "Make Reservation"; + button.Macro = "ExportButton_Click"; + button.SetPosition(15, 0, 1, 0); + button.AutomaticSize = true; + formSheet.Select(formSheet.Cells["B3"]); + + package.Workbook.CreateVBAProject(); + var module = package.Workbook.VbaProject.Modules.AddModule("ControlEvents"); + var code = new StringBuilder(); + code.AppendLine("Sub ExportButton_Click"); + code.AppendLine("Msgbox \"Here you can place the code to handle the form\""); + code.AppendLine("End Sub"); + module.Code = code.ToString(); + + package.SaveAs(FileOutputUtil.GetFileInfo("26-FormControls.xlsm")); + } + } + + private static ExcelWorksheet CreateFormSheet(ExcelPackage package) + { + var formSheet = package.Workbook.Worksheets.Add("Form"); + formSheet.Cells["A1"].Value = "Room booking"; + formSheet.Cells["A1"].Style.Font.Size = 18; + formSheet.Cells["A1"].Style.Font.Bold = true; + formSheet.Column(1).Width = 30; + formSheet.Column(2).Width = 60; + formSheet.Cells.Style.Fill.SetBackground(Color.Gray); + for (int row = 1; row <= 18; row++) + { + formSheet.Row(row).Height = 25; + } + + return formSheet; + } + + private static ExcelWorksheet CreateDataSheet(ExcelPackage package) + { + var dataSheet = package.Workbook.Worksheets.Add("Data"); + dataSheet.Cells["A1"].Value = "Man"; + dataSheet.Cells["A2"].Value = "Woman"; + + dataSheet.Cells["B1"].Value = "Garden view"; + dataSheet.Cells["B2"].Value = "Sea view"; + dataSheet.Cells["B3"].Value = "Parking lot view"; + + dataSheet.Hidden = eWorkSheetHidden.Hidden; //We hide the data sheet. + + return dataSheet; + } + } +} diff --git a/26-FormControls/Readme.md b/26-FormControls/Readme.md new file mode 100644 index 0000000..13b9b0e --- /dev/null +++ b/26-FormControls/Readme.md @@ -0,0 +1,8 @@ +# 25 - Form Controls +This samples demonstrates how to Add form controls, like drop-downs, buttons and radiobuttons to a worksheet. +It also demonstrates how to group drawings together and connect them to a VBA macro. + +### [FormControlsSample.cs](FormControlsSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 48f101d..27ab0ad 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,11 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.4.0\lib\net45\EPPlus.dll + + packages\EPPlus.5.5.0\lib\net45\EPPlus.dll + + + packages\Microsoft.IO.RecyclableMemoryStream.1.3.6\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll @@ -79,6 +82,7 @@ + @@ -117,6 +121,8 @@ + + @@ -128,6 +134,7 @@ + @@ -152,6 +159,8 @@ + + PreserveNewest diff --git a/Readme.md b/Readme.md index 837c7eb..6b9b848 100644 --- a/Readme.md +++ b/Readme.md @@ -27,6 +27,11 @@ The solution can be opened in Visual Studio for Windows. |19|[Encryption and protection](/19-EncryptionAndProtection/)|This sample produces a quiz, where the template workbook is encrypted and password protected.| |20|[Create filesystem report](/20-CreateFileSystemReport/)|Demonstrates usage of styling, printer settings, rich text, pie-, doughnut- and bar-charts, freeze panes| |21|[VBA - Visual Basic for Applications](/21-VBA/)|Demonstrates EPPlus support for VBA, includes a battleship game| +|22|[Ignore errors](/22-IgnoreErrors/)|Various samples on how to ignore error on cells.| +|23|[Comments](/23-Comments/)|Sample showing how to add notes and threaded comments.| +|24|[Slicers](/24-Slicers/)|Sample showing how to add Pivot Table slicers and Tabel slicers +|25|[Export to/from DataTable](/25-ImportAndExportDataTable)|Sample showing import/export rangedata with System.Data.DataTable +|26|[Form controls](/26-FormControls)|Sample showing how to add differnt form controls and how to group drawings. ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. diff --git a/Sample_Main.cs b/Sample_Main.cs index cea0b9c..b15d455 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -208,11 +208,23 @@ await ChartsAndThemesSample.RunAsync(connectionStr, SlicerSample.Run(connectionStr); Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); Console.WriteLine(); + + //Sample 25 - Import and Export DataTable + Console.WriteLine("Running sample 25 - Import and Export DataTable"); + DataTableSample.Run(connectionStr); + Console.WriteLine("Sample 25 finished."); + Console.WriteLine(); + + //Sample 26 - Form Controls & Drawing Groups + Console.WriteLine("Running sample 26 - Form controls"); + FormControlsSample.Run(); + Console.WriteLine("Sample 26 finished."); + Console.WriteLine(); } catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); - } + } var prevColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"Genereted sample workbooks can be found in {FileOutputUtil.OutputDir.FullName}"); diff --git a/packages.config b/packages.config index 15a7550..c703d8e 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,8 @@  - + + From 30c6fd12e956e8cd0aaf8b65527dad6f774efcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Fri, 12 Mar 2021 16:05:45 +0100 Subject: [PATCH 07/18] Changes and new samples for version 5.6 --- 18-PivotTables/PivotTablesSample.cs | 4 +- 18-PivotTables/PivotTablesStylingSample.cs | 244 +++++++++++++++ 18-PivotTables/Readme.md | 3 +- 24-Slicers/Readme.md | 2 +- 24-Slicers/SlicerSample.cs | 42 +-- 27-CustomNamedStyles/Readme.md | 8 + .../TableSlicerStyleSample.cs | 281 ++++++++++++++++++ 28-Tables/Readme.md | 9 + 28-Tables/TablesSample.cs | 181 +++++++++++ EPPlus.Sample.NET.csproj | 13 +- Readme.md | 2 + Sample_Main.cs | 18 +- packages.config | 4 +- 13 files changed, 783 insertions(+), 28 deletions(-) create mode 100644 18-PivotTables/PivotTablesStylingSample.cs create mode 100644 27-CustomNamedStyles/Readme.md create mode 100644 27-CustomNamedStyles/TableSlicerStyleSample.cs create mode 100644 28-Tables/Readme.md create mode 100644 28-Tables/TablesSample.cs diff --git a/18-PivotTables/PivotTablesSample.cs b/18-PivotTables/PivotTablesSample.cs index 46b9add..3f5aa8c 100644 --- a/18-PivotTables/PivotTablesSample.cs +++ b/18-PivotTables/PivotTablesSample.cs @@ -108,6 +108,8 @@ private static ExcelPivotTable CreatePivotTableWithDataGrouping(ExcelPackage pck var rowField = pivotTable2.RowFields.Add(pivotTable2.Fields["OrderDate"]); //This is a date field so we want to group by Years and quaters. This will create one additional field for years. rowField.AddDateGrouping(eDateGroupBy.Years | eDateGroupBy.Quarters); + rowField.Name = "Quarters"; //We rename the field OrderDate to Quarters. + //Get the Quaters field and change the texts var quaterField = pivotTable2.Fields.GetDateGroupField(eDateGroupBy.Quarters); quaterField.Items[0].Text = "<"; //Values below min date, but we use auto so its not used @@ -212,7 +214,7 @@ private static ExcelPivotTable CreatePivotTableWithACalculatedField(ExcelPackage var pivotTable4 = wsPivot4.PivotTables.Add(wsPivot4.Cells["A3"], pivotCache, "PerWithCalculatedField"); pivotTable4.RowFields.Add(pivotTable4.Fields["CompanyName"]); - pivotTable4.RowFields.Add(pivotTable4.Fields["OrderDate"]); + //Be careful with formulas as they are not validated and can cause the pivot table to become corrupt. //Be careful with formulas as they can cause the pivot table to become corrupt if they are entered invalidly. var calcField = pivotTable4.Fields.AddCalculatedField("Total", "'OrderValue'+'Tax'+'Freight'"); diff --git a/18-PivotTables/PivotTablesStylingSample.cs b/18-PivotTables/PivotTablesStylingSample.cs new file mode 100644 index 0000000..2252cf2 --- /dev/null +++ b/18-PivotTables/PivotTablesStylingSample.cs @@ -0,0 +1,244 @@ +/************************************************************************************************* + Required Notice: Copyright (C) EPPlus Software AB. + This software is licensed under PolyForm Noncommercial License 1.0.0 + and may only be used for noncommercial purposes + https://polyformproject.org/licenses/noncommercial/1.0.0/ + + A commercial license to use this software can be purchased at https://epplussoftware.com + ************************************************************************************************* + Date Author Change + ************************************************************************************************* + 01/27/2020 EPPlus Software AB Initial release EPPlus 5 + *************************************************************************************************/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using OfficeOpenXml; +using System.Data.SqlClient; +using OfficeOpenXml.Table.PivotTable; +using OfficeOpenXml.Drawing.Chart; +using OfficeOpenXml.Drawing.Chart.Style; +using System.Data.SQLite; +using OfficeOpenXml.Drawing; +using System.Drawing; +using OfficeOpenXml.Style; +using OfficeOpenXml.Table; + +namespace EPPlusSamples.PivotTables +{ + /// + /// This class shows how to use pivottables + /// + public static class PivotTablesStylingSample + { + public static string Run() + { + FileInfo templateFile = FileOutputUtil.GetFileInfo("18-PivotTables.xlsx", false); + FileInfo newFile = FileOutputUtil.GetFileInfo("18-PivotTables-Styling.xlsx"); + using ( ExcelPackage pck = new ExcelPackage(newFile, templateFile)) + { + //These two sample shows how to style different parts on the pivot table using pivot areas. + StylePivotTable1_PerCountry(pck); + StylePivotTable2_WithDataGrouping(pck); + + //This sample styles the pivot table by combining a named style and use pivot areas. For named styles please also see sample 27 + StylePivotTable3_WithPageFilter(pck); + //This sample styles the pivot table using pivot areas in various ways and create a custom named slicer style for the slicers. + StylePivotTable4_WithASlicer(pck); + + //Adds a slicer and do some styling. + StylePivotTable5_WithACalculatedField(pck); + //Sets the pivot table into tabular mode to display the filter boxes on the row fields then styles the button fields + StylePivotTable6_CaptionFilter(pck); + + pck.Save(); + } + return newFile.FullName; + } + + private static void StylePivotTable1_PerCountry(ExcelPackage pck) + { + var pivot1 = pck.Workbook.Worksheets["PivotSimple"].PivotTables[0]; + //First add a style that sets the font and color for the entire pivot table. + var styleWholeTable = pivot1.Styles.AddWholeTable(); + styleWholeTable.Style.Font.Name = "Times New Roman"; + styleWholeTable.Style.Font.Color.SetColor(eThemeSchemeColor.Accent2); + + //Adds new style for all labels in the pivot table. Later added styles will override earlier added styles. + var styleLabels = pivot1.Styles.AddAllLabels(); + styleLabels.Style.Font.Color.SetColor(eThemeSchemeColor.Accent4); + styleLabels.Style.Font.Italic = true; + + //This style sets the colors for the labels of the first row field. + var styleLabelsForRowField = pivot1.Styles.AddLabel(pivot1.RowFields[0]); + styleLabelsForRowField.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + + //This style sets the color and font italic for the grand row of the first row field. + var styleLabelsForGrandTotal = pivot1.Styles.AddLabel(pivot1.RowFields[0]); + styleLabelsForGrandTotal.Style.Font.Color.SetColor(Color.Red); + styleLabelsForGrandTotal.Style.Font.Italic = true; + styleLabelsForGrandTotal.GrandRow = true; + + //Set the style of the grand total for the data. + var styleDataForGrandTotal = pivot1.Styles.AddData(); + styleDataForGrandTotal.Style.Font.Color.SetColor(eThemeSchemeColor.Accent6); + styleDataForGrandTotal.GrandRow = true; + } + private static void StylePivotTable2_WithDataGrouping(ExcelPackage pck) + { + var pivot2 = pck.Workbook.Worksheets["PivotDateGrp"].PivotTables[0]; + + //Add a gradient fill for the page field label. + var stylePagebutton = pivot2.Styles.AddButtonField(ePivotTableAxis.PageAxis); + stylePagebutton.Style.Fill.Style = eDxfFillStyle.GradientFill; + stylePagebutton.Style.Fill.Gradient.Degree = 90; + var c1=stylePagebutton.Style.Fill.Gradient.Colors.Add(0); + c1.Color.SetColor(Color.LightSteelBlue); + var c2 = stylePagebutton.Style.Fill.Gradient.Colors.Add(1); + c2.Color.SetColor(Color.DarkSlateBlue); + stylePagebutton.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + + //Sets the style for the page filter cell + var pageStyle = pivot2.Styles.AddLabel(pivot2.PageFields[0]); + pageStyle.Style.Fill.BackgroundColor.SetColor(Color.DarkGreen); + stylePagebutton.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + + //Styles the area to the left of the column axis button field. + var topLeft = pivot2.Styles.AddTopStart(); + topLeft.Style.Fill.BackgroundColor.SetColor(Color.Green); + + //Set the style for the column axis button field label + var columnStyle = pivot2.Styles.AddButtonField(ePivotTableAxis.ColumnAxis); + columnStyle.Style.Fill.BackgroundColor.SetColor(Color.Yellow); + columnStyle.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + + //Styles the area to the right of the the column axis button field label. + var topRight = pivot2.Styles.AddTopEnd(); + topRight.Style.Fill.BackgroundColor.SetColor(Color.Red); + + + + + var rowLableStyleQuarter = pivot2.Styles.AddLabel(pivot2.Fields["Quarters"]); + rowLableStyleQuarter.Style.Font.Italic = true; + + var rowLableStyleYear = pivot2.Styles.AddLabel(pivot2.Fields["Years"]); + rowLableStyleYear.Style.Font.Underline = ExcelUnderLineType.Single; + + //Here we style a label for a single row item. We add all the row fields to the pivot area and then add the values we want to style. Note that the value and data type must match the value in the pivot field. + var labelItem1 = pivot2.Styles.AddLabel(pivot2.Fields["Name"], pivot2.Fields["Years"], pivot2.Fields["Quarters"]); + labelItem1.Conditions.Fields[0].Items.AddByValue("Christina Parker"); + labelItem1.Conditions.Fields[1].Items.AddByValue(2017D); //Double here to match the value in the pivot table + labelItem1.Conditions.Fields[2].Items.AddByValue("Q4"); + labelItem1.Style.Font.Color.SetColor(Color.DarkRed); + + //Here we style a data cell for a single row item. We add all the row fields and the data fields we want to the pivot area and then add the values of the row fields. + var dataItem1 = pivot2.Styles.AddData(pivot2.Fields["Name"], pivot2.Fields["Years"], pivot2.Fields["Quarters"]); + dataItem1.Conditions.Fields[0].Items.AddByValue("Hellen Kuhlman"); + dataItem1.Conditions.Fields[1].Items.AddByValue(2017D); //Double here to match the value in the pivot table + dataItem1.Conditions.Fields[2].Items.AddByValue("Q3"); + dataItem1.Conditions.Fields[2].Items.AddByValue("Q4"); + dataItem1.Conditions.DataFields.Add(pivot2.DataFields[0]); //OrderValue + dataItem1.Conditions.DataFields.Add(pivot2.DataFields[2]); //Freight + dataItem1.Style.Font.Color.SetColor(Color.DarkMagenta); + } + private static void StylePivotTable3_WithPageFilter(ExcelPackage pck) + { + var pivot3 = pck.Workbook.Worksheets["PivotWithPageField"].PivotTables[0]; + + //Create a named pivot table style with Dark28 to start from and make some minor changes. + var styleName = "CustomPivotTableStyle1"; + var style = pck.Workbook.Styles.CreatePivotTableStyle(styleName, PivotTableStyles.Dark28); + style.HeaderRow.Style.Font.Italic = true; + style.TotalRow.Style.Font.Italic = true; + pivot3.StyleName = styleName; + + //Set the style for the header of the data fields. + var style1 = pivot3.Styles.AddLabel(); + style1.Conditions.DataFields.Add(pivot3.DataFields[0]); + style1.Conditions.DataFields.Add(pivot3.DataFields[1]); + style1.Conditions.DataFields.Add(pivot3.DataFields[2]); + style1.Style.Font.Underline = ExcelUnderLineType.Single; + + //Here we mark the grand total cell for the last data column. + var style2 = pivot3.Styles.AddData(); + style2.Conditions.DataFields.Add(pivot3.DataFields[2]); + style2.GrandRow = true; + style2.Style.Font.Color.SetColor(Color.Red); + + //Here we set the number format for the OrderDate items for a specific name. + var style3 = pivot3.Styles.AddData(pivot3.Fields["Name"], pivot3.Fields["OrderDate"]); + style3.Conditions.Fields[0].Items.AddByValue("Jason Zemlak"); + style3.Conditions.DataFields.Add(pivot3.DataFields[2]); + style3.Style.NumberFormat.Format="#,##0.00"; + + //Here we set the number format of the total cell only. + var style4 = pivot3.Styles.AddData(pivot3.Fields["Name"]); + style4.Conditions.Fields[0].Items.AddByValue("Jason Zemlak"); + style4.Conditions.DataFields.Add(pivot3.DataFields[2]); + style4.Style.NumberFormat.Format = "#,##0.00000"; + style4.CollapsedLevelsAreSubtotals = true; //Only for the total only. Setting this to false will set the format for the sub items as well + } + + private static void StylePivotTable4_WithASlicer(ExcelPackage pck) + { + //This method connects a slicer to the pivot table. Also see sample 24 for more detailed samples on slicers. + var wsPivot4 = pck.Workbook.Worksheets["PivotWithSlicer"]; + var pivotTable4= wsPivot4.PivotTables[0]; + + //Slicers can also be styled by creating a named style. Here we use the build in Light 5 as a template and changes the font of the slicer. + //See Sample 27 for more detailed samples. + var slicer = pivotTable4.Fields["CompanyName"].Slicer; + var styleName = "CustomSlicerStyle1"; + var style = pck.Workbook.Styles.CreateSlicerStyle(styleName, eSlicerStyle.Light5); + style.WholeTable.Style.Font.Name = "Stencil"; + slicer.StyleName = styleName; + + var style1 = pivotTable4.Styles.Add(); + style1.GrandRow = true; //The pivot area will apply to the Grand Row only. + style1.DataOnly = false; //DataOnly is true by default, so to apply the style to the entire row we set it to false. + style1.Style.Font.Size = 18; + } + private static void StylePivotTable5_WithACalculatedField(ExcelPackage pck) + { + //This method connects a slicer to the pivot table. Also see sample 24 for more detailed samples on slicers. + var wsPivot5 = pck.Workbook.Worksheets["PivotWithCalculatedField"]; + //Create a new pivot table using the same cache as pivot table 2. + var pivotTable5 = wsPivot5.PivotTables[0]; + + //Sets the entire calculated column fill to solid - Accent 4 + + //This sets the top-right column. Offset C1 means means offset 3 columns offset within the top end area. + var style1 = pivotTable5.Styles.AddTopEnd("C1"); + style1.Style.Fill.BackgroundColor.SetColor(eThemeSchemeColor.Accent4); + + //Sets the fill for the label + var style2 = pivotTable5.Styles.AddLabel(); + style2.Conditions.DataFields.Add(pivotTable5.DataFields[3]); //Adds a style for the calculated field + style2.Style.Fill.BackgroundColor.SetColor(eThemeSchemeColor.Accent4); + + //Sets the fill for the data part of the calculated field. + var style3 = pivotTable5.Styles.Add(); + style3.Conditions.DataFields.Add(pivotTable5.DataFields[3]); //Add a style for the calculated field + style3.LabelOnly = false; + style3.Style.Fill.BackgroundColor.SetColor(eThemeSchemeColor.Accent4); + } + private static void StylePivotTable6_CaptionFilter(ExcelPackage pck) + { + var wsPivot6 = pck.Workbook.Worksheets["PivotWithCaptionFilter"]; + var pivotTable6 = wsPivot6.PivotTables[0]; + + //Set the pivot table labels in tabular form to get the filter buttons for all row fields. + pivotTable6.SetCompact(false); + + //Set the style for the buttons. + var style1 = pivotTable6.Styles.AddButtonField(pivotTable6.RowFields[0]); + style1.Style.Font.Color.SetColor(eThemeSchemeColor.Accent4); + + var style2 = pivotTable6.Styles.AddButtonField(ePivotTableAxis.RowAxis, 1); //Field with index 1 in the row axis. + style2.Style.Font.Color.SetColor(eThemeSchemeColor.Accent4); + } + } +} diff --git a/18-PivotTables/Readme.md b/18-PivotTables/Readme.md index 9297423..9e85573 100644 --- a/18-PivotTables/Readme.md +++ b/18-PivotTables/Readme.md @@ -1,5 +1,6 @@ # 18 - Pivot tables -This sample demonstrates the Pivot table functionality of EPPlus. +The PivotTablesSample class demonstrates the Pivot table functionality of EPPlus. +The PivotTablesStylingSample class reads the pivot sample and shows how to style different parts of a pivot table or use a custom named style. ### [PivotTablesSample.cs](PivotTablesSample.cs) diff --git a/24-Slicers/Readme.md b/24-Slicers/Readme.md index 2775e3e..5f8bb72 100644 --- a/24-Slicers/Readme.md +++ b/24-Slicers/Readme.md @@ -1,5 +1,5 @@ # 24 - Slicers -These samples demonstrates slicer functionality of EPPlus. +These samples demonstrates the slicer functionality of EPPlus. A slicer is a drawing object that reflects the filter for various data objects. EPPlus implement support for table and pivot table slicers. diff --git a/24-Slicers/SlicerSample.cs b/24-Slicers/SlicerSample.cs index e0fd837..3aebe32 100644 --- a/24-Slicers/SlicerSample.cs +++ b/24-Slicers/SlicerSample.cs @@ -1,6 +1,6 @@ using OfficeOpenXml; +using OfficeOpenXml.Drawing; using OfficeOpenXml.Filter; -using System; using System.Data.SQLite; namespace EPPlusSamples @@ -11,7 +11,7 @@ public static void Run(string connectionString) { using (var p = new ExcelPackage()) { - //A sample with a table and several slicers. + //Creates a worksheet with one table and several slicers. TableSlicerSample(p, connectionString); //Creates the source data for the pivot tables in a separate sheet. @@ -19,6 +19,7 @@ public static void Run(string connectionString) //Create a pivot table with a slicer connected to one field. PivotTableSlicerSample(p); + //Create three slicers and two pivot tables, one that connects to both tables and two that connect to each of the tables. PivotTableOneSlicerToMultiplePivotTables(p); p.SaveAs(FileOutputUtil.GetFileInfo("24-Slicers.xlsx")); @@ -30,7 +31,7 @@ private static void PivotTableOneSlicerToMultiplePivotTables(ExcelPackage p) var wsSource = p.Workbook.Worksheets["PivotTableSourceData"]; var wsPivot = p.Workbook.Worksheets.Add("OneSlicerToTwoPivotTables"); - var pivotTable1 = wsPivot.PivotTables.Add(wsPivot.Cells["D15"], wsSource.Cells[wsSource.Dimension.Address], "PivotTable1"); + var pivotTable1 = wsPivot.PivotTables.Add(wsPivot.Cells["A15"], wsSource.Cells[wsSource.Dimension.Address], "PivotTable1"); pivotTable1.RowFields.Add(pivotTable1.Fields["Company Name"]); pivotTable1.DataFields.Add(pivotTable1.Fields["Order Value"]); pivotTable1.DataFields.Add(pivotTable1.Fields["Tax"]); @@ -38,7 +39,7 @@ private static void PivotTableOneSlicerToMultiplePivotTables(ExcelPackage p) pivotTable1.DataOnRows = false; //To connect a slicer to multiple pivot tables the tables need to use the same pivot table cache, so we use pivotTable1's cache as source to pivotTable2... - var pivotTable2 = wsPivot.PivotTables.Add(wsPivot.Cells["H15"], pivotTable1.CacheDefinition, "PivotTable2"); + var pivotTable2 = wsPivot.PivotTables.Add(wsPivot.Cells["F15"], pivotTable1.CacheDefinition, "PivotTable2"); pivotTable2.RowFields.Add(pivotTable2.Fields["Country"]); pivotTable2.DataFields.Add(pivotTable2.Fields["Order Value"]); pivotTable2.DataFields.Add(pivotTable2.Fields["Tax"]); @@ -55,13 +56,15 @@ private static void PivotTableOneSlicerToMultiplePivotTables(ExcelPackage p) var slicer2 = pivotTable1.Fields["Company Name"].AddSlicer(); slicer2.Caption = "Company Name - PivotTable1"; - slicer2.SetPosition(0, 0, 3, 0); - slicer2.To.Column = 7; + slicer2.ChangeCellAnchor(eEditAs.Absolute); + slicer2.SetPosition(0, 192); + slicer2.SetSize(256, 260); var slicer3 = pivotTable2.Fields["Order date"].AddSlicer(); slicer3.Caption = "Order date - PivotTable2"; - slicer3.SetPosition(0, 0, 7, 0); - slicer3.To.Column = 11; + slicer3.ChangeCellAnchor(eEditAs.Absolute); + slicer3.SetPosition(0, 448); + slicer3.SetSize(256, 260); } private static void TableSlicerSample(ExcelPackage p, string connectionString) { @@ -75,28 +78,29 @@ private static void TableSlicerSample(ExcelPackage p, string connectionString) { using (var sqlReader = sqlCmd.ExecuteReader()) { - var range = worksheet1.Cells["A1"].LoadFromDataReader(sqlReader, true, "tblSalesData", OfficeOpenXml.Table.TableStyles.Medium6); + var range = worksheet1.Cells["A14"].LoadFromDataReader(sqlReader, true, "tblSalesData", OfficeOpenXml.Table.TableStyles.Medium6); var tbl = worksheet1.Tables.GetFromRange(range); range.Offset(1, 4, range.Rows - 1, 1).Style.Numberformat.Format = "yyyy-MM-dd"; range.Offset(1, 5, range.Rows - 1, 3).Style.Numberformat.Format = "#,##0"; + range.AutoFitColumns(); //You can either add a slicer via the table column... var slicer1 = tbl.Columns[0].AddSlicer(); //Filter values are compared to the Text property of the cell. slicer1.FilterValues.Add("Barton-Veum"); slicer1.FilterValues.Add("Christiansen LLC"); - slicer1.SetPosition(2, 0, 10, 0); + slicer1.SetPosition(0, 0, 0, 0); //... or you can add it via the drawings collection. var slicer2 = worksheet1.Drawings.AddTableSlicer(tbl.Columns["Country"]); - slicer2.SetPosition(2, 0, 13, 0); + slicer2.SetPosition(0,192); //A slicer also supports date groups... var slicer3 = tbl.Columns["Order Date"].AddSlicer(); slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 6)); slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 7)); slicer3.FilterValues.Add(new ExcelFilterDateGroupItem(2017, 8)); - slicer3.SetPosition(2, 0, 16, 0); + slicer3.SetPosition(0, 384); //... You can also add a slicer to another worksheet, if you use the drawings collection... var slicer4 = worksheet2.Drawings.AddTableSlicer(tbl.Columns["E-Mail"]); @@ -104,12 +108,16 @@ private static void TableSlicerSample(ExcelPackage p, string connectionString) slicer4.Description = "This slicer reference a table in another worksheet."; slicer4.SetPosition(1, 0, 1, 0); slicer4.To.Column = 7; //Set the end position anchor to column H, to make the slicer wider. + + var shape = worksheet2.Drawings.AddShape("InfoText", eShapeStyle.Rect); + shape.SetPosition(1, 0, 8, 0); + shape.Text = "This slicer filters the table located in the TableSlicer worksheet"; } } sqlConn.Close(); } - worksheet1.Cells.AutoFitColumns(); - } + worksheet1.View.FreezePanes(14, 1); + } private static void PivotTableSlicerSample(ExcelPackage p) { var wsSource = p.Workbook.Worksheets["PivotTableSourceData"]; @@ -126,13 +134,13 @@ private static void PivotTableSlicerSample(ExcelPackage p) slicer1.SetPosition(0, 0, 10, 0); slicer1.SetSize(400, 208); slicer1.Style = eSlicerStyle.Light4; - slicer1.Cache.Data.Items.GetByValue("Brown Kutch").Hidden=true; + slicer1.Cache.Data.Items.GetByValue("Brown Kutch").Hidden = true; slicer1.Cache.Data.Items.GetByValue("Tierra Ratke").Hidden = true; slicer1.Cache.Data.Items.GetByValue("Jamarcus Schimmel").Hidden = true; //Add a column with two columns and start showing the item 3. - slicer1.ColumnCount = 2; - slicer1.StartItem = 3; + slicer1.ColumnCount = 2; //Use two columns on this slicer + slicer1.StartItem = 3; //First visible item is 3 slicer1.Cache.Data.CrossFilter = eCrossFilter.ShowItemsWithNoData; slicer1.Cache.Data.SortOrder = eSortOrder.Descending; } diff --git a/27-CustomNamedStyles/Readme.md b/27-CustomNamedStyles/Readme.md new file mode 100644 index 0000000..a319bea --- /dev/null +++ b/27-CustomNamedStyles/Readme.md @@ -0,0 +1,8 @@ +# 27 - Custom table and slicer styles +These samples demonstrates how to create your own table / pivot table or slicer styles using EPPlus. +EPPlus supports creating named styles from scratch or use a buildin style as a template for your custom style. + +### [TableSlicerStyleSample.cs](TableSlicerStyleSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/27-CustomNamedStyles/TableSlicerStyleSample.cs b/27-CustomNamedStyles/TableSlicerStyleSample.cs new file mode 100644 index 0000000..ca69a6f --- /dev/null +++ b/27-CustomNamedStyles/TableSlicerStyleSample.cs @@ -0,0 +1,281 @@ +using OfficeOpenXml; +using OfficeOpenXml.Drawing; +using OfficeOpenXml.Filter; +using OfficeOpenXml.Style; +using OfficeOpenXml.Table; +using OfficeOpenXml.Table.PivotTable; +using System.Data.SQLite; +using System.Drawing; + +namespace EPPlusSamples +{ + /// + /// This sample demonstrates how to add custom named styles for + /// + public static class CustomTableSlicerStyleSample + { + public static void Run(string connectionString) + { + using (var p = new ExcelPackage()) + { + CreateTableStyles(p); + CreatePivotTableStyles(p); + CreateSlicerStyles(p); + + p.SaveAs(FileOutputUtil.GetFileInfo("27-TableAndSlicerStyles.xlsx")); + } + } + + private static void CreateTableStyles(ExcelPackage p) + { + var wsTables = p.Workbook.Worksheets.Add("CustomStyledTables"); + + //Create a custom table style from scratch and adds a fill gradient fill style + var customTableStyle1 = "CustomTableStyle1"; + CreateCustomTableStyleFromScratch(p, customTableStyle1); + + //This samples creates a style with the build in table style Dark11 as template and set the header row and table row font to italic. + var customTableStyle2 = "CustomTableStyleFromDark11"; + CreateCustomTableStyleFromBuildInTableStyle(p, customTableStyle2); + + //This samples creates a style with the build in table style Medium11 as template and set the header row and table row font to italic. + var customTableStyle3 = "CustomTableAndPivotTableStyleFromDark11"; + CreateCustomTableAndPivotTableStyleFromBuildInStyle(p, customTableStyle3); + + + ExcelTable tbl1 = CreateTable(wsTables, "Table1"); + tbl1.StyleName = customTableStyle1; + + ExcelTable tbl2 = CreateTable(wsTables, "Table2", 9, 1); + tbl2.StyleName = customTableStyle2; + + ExcelTable tbl3 = CreateTable(wsTables, "Table3", 17, 1); + tbl3.StyleName = customTableStyle3; + + wsTables.Cells.AutoFitColumns(); + } + + private static void CreatePivotTableStyles(ExcelPackage p) + { + var wsPivotTable = p.Workbook.Worksheets.Add("CustomStyledPivotTables"); + + //Create a pivot table style from scratch. + var customPivotTableStyle1 = "CustomPivotTableStyle1"; + CreateCustomPivotTableStyleFromScratch(p, customPivotTableStyle1); + + //This samples creates a style with the build in table style Dark11 as template and set the header row and table row font to italic. + var customPivotTableStyle2 = "CustomPivotTableStyleFromMedium25"; + CreateCustomPivotTableStyleFromBuildInTableStyle(p, customPivotTableStyle2); + + //Create a pivot table and use the named style we created earlier in this sample for both pivot tables and tables. + var pt1 = CreatePivotTable(wsPivotTable, "PivotTable1", p.Workbook.Worksheets[0].Tables[0], wsPivotTable.Cells["A3"]); + pt1.StyleName = "CustomTableAndPivotTableStyleFromDark11"; + + var pt2 = CreatePivotTable(wsPivotTable, "PivotTable2", p.Workbook.Worksheets[0].Tables[0], wsPivotTable.Cells["A15"]); + pt2.StyleName = customPivotTableStyle1; + + var pt3 = CreatePivotTable(wsPivotTable, "PivotTable3", p.Workbook.Worksheets[0].Tables[0], wsPivotTable.Cells["A30"]); + pt3.StyleName = customPivotTableStyle2; + + } + + private static void CreateSlicerStyles(ExcelPackage p) + { + var wsSlicers = p.Workbook.Worksheets.Add("CustomStyledSlicers"); + var tbl=CreateTable(wsSlicers, "TableForSlicer1"); + + var slicer1=tbl.Columns[0].AddSlicer(); + slicer1.SetPosition(100, 300); + + //Create a slicer style from scratch. + var customSlicerStyle1 = "CustomSlicerStyleConsole"; + CreateCustomSlicerStyleFromScratch(p, customSlicerStyle1); + slicer1.StyleName = customSlicerStyle1; + + var slicer2 = tbl.Columns[1].AddSlicer(); + slicer2.SetPosition(100, 500); + + var customSlicerStyle2 = "CustomSlicerStyleFromStyleDark2"; + CreateCustomSlicerStyleFromBuildInStyle(p, customSlicerStyle2); + slicer2.StyleName = customSlicerStyle2; + } + + private static void CreateCustomSlicerStyleFromBuildInStyle(ExcelPackage p, string styleName) + { + //Create a custom named slicer style that applies users the build in style Dark4 as template and make some minor modifications. + var customSlicerStyle = p.Workbook.Styles.CreateSlicerStyle(styleName, eSlicerStyle.Dark4); + customSlicerStyle.WholeTable.Style.Font.Name = "Broadway"; + customSlicerStyle.HeaderRow.Style.Font.Italic = true; + customSlicerStyle.HeaderRow.Style.Border.Bottom.Color.SetColor(Color.Red); + } + + private static void CreateCustomSlicerStyleFromScratch(ExcelPackage p, string styleName) + { + //Create a named style that applies to slicers with a console feel to the style. + var customSlicerStyle = p.Workbook.Styles.CreateSlicerStyle(styleName); + + customSlicerStyle.WholeTable.Style.Font.Name = "Consolas"; + customSlicerStyle.WholeTable.Style.Font.Size = 12; + customSlicerStyle.WholeTable.Style.Font.Color.SetColor(Color.WhiteSmoke); + customSlicerStyle.WholeTable.Style.Fill.BackgroundColor.SetColor(Color.Black); + + customSlicerStyle.HeaderRow.Style.Fill.BackgroundColor.SetColor(Color.LightGray); + customSlicerStyle.HeaderRow.Style.Font.Color.SetColor(Color.Black); + + customSlicerStyle.SelectedItemWithData.Style.Fill.BackgroundColor.SetColor(Color.Gray); + customSlicerStyle.SelectedItemWithData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.DarkGray); + + customSlicerStyle.SelectedItemWithNoData.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(0xFF, 64, 64, 64)); + customSlicerStyle.SelectedItemWithNoData.Style.Font.Color.SetColor(Color.DarkGray); + customSlicerStyle.SelectedItemWithNoData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.DarkGray); + + customSlicerStyle.UnselectedItemWithData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.DarkGray); + customSlicerStyle.UnselectedItemWithNoData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.DarkGray); + + customSlicerStyle.UnselectedItemWithNoData.Style.Font.Color.SetColor(Color.DarkGray); + + customSlicerStyle.HoveredSelectedItemWithData.Style.Fill.BackgroundColor.SetColor(Color.DarkGray); + customSlicerStyle.HoveredSelectedItemWithData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.WhiteSmoke); + + customSlicerStyle.HoveredSelectedItemWithNoData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.WhiteSmoke); + + customSlicerStyle.HoveredUnselectedItemWithData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.WhiteSmoke); + customSlicerStyle.HoveredUnselectedItemWithNoData.Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.WhiteSmoke); + } + + #region Table Styles + private static void CreateCustomTableStyleFromScratch(ExcelPackage p, string styleName) + { + //Create a named style used to tables only. + var customTableStyle = p.Workbook.Styles.CreateTableStyle(styleName); + + customTableStyle.WholeTable.Style.Font.Color.SetColor(eThemeSchemeColor.Text2); + customTableStyle.HeaderRow.Style.Font.Bold = true; + customTableStyle.HeaderRow.Style.Font.Italic = true; + + customTableStyle.HeaderRow.Style.Fill.Style = eDxfFillStyle.GradientFill; + customTableStyle.HeaderRow.Style.Fill.Gradient.Degree = 90; + + var c1 = customTableStyle.HeaderRow.Style.Fill.Gradient.Colors.Add(0); + c1.Color.SetColor(Color.LightGreen); + + var c3 = customTableStyle.HeaderRow.Style.Fill.Gradient.Colors.Add(100); + c3.Color.SetColor(Color.DarkGreen); + } + private static void CreateCustomTableStyleFromBuildInTableStyle(ExcelPackage p, string styleName) + { + //Create a new custom table style with the build in style Dark11 as template. + var customTableStyle = p.Workbook.Styles.CreateTableStyle(styleName, TableStyles.Dark11); + + customTableStyle.HeaderRow.Style.Font.Italic = true; + customTableStyle.TotalRow.Style.Font.Italic = true; + + //Set the stripe size to 2 rows for both the the row stripes + customTableStyle.FirstRowStripe.BandSize = 2; + customTableStyle.FirstRowStripe.Style.Fill.BackgroundColor.SetColor(Color.LightGreen); + + customTableStyle.SecondRowStripe.BandSize = 2; + customTableStyle.SecondRowStripe.Style.Fill.BackgroundColor.SetColor(Color.LightSkyBlue); + } + private static void CreateCustomTableAndPivotTableStyleFromBuildInStyle(ExcelPackage p, string customTableStyle3) + { + //Create a named style that can be used both for tables and pivot tables. + //We create this style from one of the build in pivot table styles - Medium13, but table styles can also be used as a parameter for this method + var customTableStyle = p.Workbook.Styles.CreateTableAndPivotTableStyle(customTableStyle3, PivotTableStyles.Medium13); + + //Set the header row and total row border to dotted. + customTableStyle.HeaderRow.Style.Border.Bottom.Style = ExcelBorderStyle.Dotted; + customTableStyle.HeaderRow.Style.Border.Bottom.Color.SetColor(Color.Gray); + + customTableStyle.TotalRow.Style.Border.Top.Style = ExcelBorderStyle.Dotted; + customTableStyle.TotalRow.Style.Border.Top.Color.SetColor(Color.Gray); + } + /// + /// Creates a table with random data used for this sample + /// + /// The worksheet + /// The name of the table + /// Start row of the table + /// Start column of the table + /// + private static ExcelTable CreateTable(ExcelWorksheet wsTables, string tableName, int rowStart = 1, int colStart = 1) + { + wsTables.Cells[rowStart, colStart].Value = "Column1"; + wsTables.Cells[rowStart, colStart + 1].Value = "Column2"; + wsTables.Cells[rowStart, colStart + 2].Value = "Column3"; + wsTables.Cells[rowStart + 1, colStart].Value = 1; + wsTables.Cells[rowStart + 1, colStart + 1].Value = 2; + wsTables.Cells[rowStart + 1, colStart + 2].Value = "Type 1"; + + wsTables.Cells[rowStart + 2, colStart].Value = 2; + wsTables.Cells[rowStart + 2, colStart + 1].Value = 4; + wsTables.Cells[rowStart + 2, colStart + 2].Value = "Type 2"; + + wsTables.Cells[rowStart + 3, colStart].Value = 3; + wsTables.Cells[rowStart + 3, colStart + 1].Value = 7; + wsTables.Cells[rowStart + 3, colStart + 2].Value = "Type 1"; + + wsTables.Cells[rowStart + 4, colStart].Value = 4; + wsTables.Cells[rowStart + 4, colStart + 1].Value = 20; + wsTables.Cells[rowStart + 4, colStart + 2].Value = "Type 3"; + + wsTables.Cells[rowStart + 5, colStart].Value = 5; + wsTables.Cells[rowStart + 5, colStart + 1].Value = 43; + wsTables.Cells[rowStart + 5, colStart + 2].Value = "Type 3"; + + var tbl = wsTables.Tables.Add(wsTables.Cells[rowStart, colStart, rowStart + 5, colStart + 2], tableName); + tbl.Columns[0].TotalsRowFunction = RowFunctions.Sum; + tbl.Columns[1].TotalsRowFunction = RowFunctions.Sum; + tbl.ShowTotal = true; + return tbl; + } + #endregion + #region Pivot Table Styles + + private static void CreateCustomPivotTableStyleFromScratch(ExcelPackage p, string styleName) + { + //Create a named style that applies only to pivot tables. + var customPivotTableStyle = p.Workbook.Styles.CreatePivotTableStyle(styleName); + + customPivotTableStyle.WholeTable.Style.Font.Color.SetColor(ExcelIndexedColor.Indexed22); + customPivotTableStyle.PageFieldLabels.Style.Font.Color.SetColor(Color.Red); + customPivotTableStyle.PageFieldValues.Style.Font.Color.SetColor(eThemeSchemeColor.Accent4); + + customPivotTableStyle.HeaderRow.Style.Font.Color.SetColor(Color.DarkGray); + customPivotTableStyle.HeaderRow.Style.Fill.Style = eDxfFillStyle.GradientFill; + customPivotTableStyle.HeaderRow.Style.Fill.Gradient.Degree = 180; + + var c1 = customPivotTableStyle.HeaderRow.Style.Fill.Gradient.Colors.Add(0); + c1.Color.SetColor(Color.LightBlue); + + var c3 = customPivotTableStyle.HeaderRow.Style.Fill.Gradient.Colors.Add(100); + c3.Color.SetColor(Color.DarkCyan); + + } + private static void CreateCustomPivotTableStyleFromBuildInTableStyle(ExcelPackage p, string styleName) + { + //Create a new custom pivot table style with the build in style Medium as template. + var customPivotTableStyle = p.Workbook.Styles.CreatePivotTableStyle(styleName, PivotTableStyles.Medium25); + + //Alter the font color of the entire table to theme color Text 2 + customPivotTableStyle.WholeTable.Style.Font.Color.SetColor(eThemeSchemeColor.Text2); + + customPivotTableStyle.HeaderRow.Style.Font.Italic = true; + customPivotTableStyle.TotalRow.Style.Font.Italic = true; + + customPivotTableStyle.FirstColumnSubheading.Style.Fill.BackgroundColor.SetColor(Color.LightGreen); + customPivotTableStyle.FirstColumnStripe.Style.Fill.BackgroundColor.SetColor(Color.LightGray); + customPivotTableStyle.FirstColumnStripe.Style.Fill.BackgroundColor.SetColor(Color.WhiteSmoke); + } + + private static ExcelPivotTable CreatePivotTable(ExcelWorksheet wsPivotTables, string pivotTableName, ExcelTable tableSource, ExcelRange range) + { + var pt = wsPivotTables.PivotTables.Add(range, tableSource, pivotTableName); + pt.RowFields.Add(pt.Fields[0]); + pt.DataFields.Add(pt.Fields[1]); + pt.PageFields.Add(pt.Fields[2]); + return pt; + } + #endregion + } +} diff --git a/28-Tables/Readme.md b/28-Tables/Readme.md new file mode 100644 index 0000000..257e913 --- /dev/null +++ b/28-Tables/Readme.md @@ -0,0 +1,9 @@ +# 28 - Tables sample +These samples demonstrates how to work with tables in EPPlus. There are serveral more samples of this, so also checkout sample 4, 5 13, 18, 20, 24 +First method shows how to add a calculated column to your table. +The second metod show how to style a table, add a custom total formula and adding rows. +The third method adds a slicer to filter a table column. +### [TablesSample.cs](TablesSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/28-Tables/TablesSample.cs b/28-Tables/TablesSample.cs new file mode 100644 index 0000000..c6fc7fd --- /dev/null +++ b/28-Tables/TablesSample.cs @@ -0,0 +1,181 @@ +using OfficeOpenXml; +using OfficeOpenXml.Drawing; +using OfficeOpenXml.Table; +using System; +using System.Data.SQLite; +using System.Drawing; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + /// + /// This sample demonstrates how work with Excel tables in EPPlus. + /// Tables can easily be added by many of the ExcelRange - Load methods as demonstrated in earlier samples. + /// This sample will focus on how to add and setup tables from the ExcelWorksheet.Tables collection. + /// + public static class TablesSample + { + public static async Task RunAsync(string connectionString) + { + using (var p = new ExcelPackage()) + { + await CreateTableWithACalculatedColumnAsync(connectionString, p).ConfigureAwait(false); + await StyleTablesAsync(connectionString, p).ConfigureAwait(false); + await CreateTableFilterAndSlicerAsync(connectionString, p).ConfigureAwait(false); + + p.SaveAs(FileOutputUtil.GetFileInfo("28-Tables.xlsx")); + } + } + /// + /// This sample creates a table with a calculated column. A totals row is added and styling is applied to some of the columns. + /// + /// The connection string to the database + /// The package + /// + private static async Task CreateTableWithACalculatedColumnAsync(string connectionString, ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("SimpleTable"); + + var range = await LoadDataAsync(connectionString, ws).ConfigureAwait(false); + var tbl1=ws.Tables.Add(range, "Table1"); + + tbl1.ShowTotal = true; + //Format the OrderDate column and add a Count Numbers subtotal. + tbl1.Columns["OrderDate"].TotalsRowFunction = RowFunctions.CountNums; + tbl1.Columns["OrderDate"].DataStyle.NumberFormat.Format = "yyyy-MM-dd"; + tbl1.Columns["OrderDate"].TotalsRowStyle.NumberFormat.Format = "#,##0"; + + //Format the OrderValue column and add a Sum subtotal. + tbl1.Columns["OrderValue"].TotalsRowFunction = RowFunctions.Sum; + tbl1.Columns["OrderValue"].DataStyle.NumberFormat.Format = "#,##0"; + tbl1.Columns["OrderValue"].TotalsRowStyle.NumberFormat.Format = "#,##0"; + + //Adds a calculated formula referencing the OrderValue column within the same row. + tbl1.Columns.Add(1); + var addedcolumn = tbl1.Columns[tbl1.Columns.Count - 1]; + addedcolumn.Name = "OrderValue with Tax"; + addedcolumn.CalculatedColumnFormula = "Table1[[#This Row],[OrderValue]] * 110%"; //Sets the calculated formula referencing the OrderValue column within this row. + addedcolumn.TotalsRowFunction = RowFunctions.Sum; + addedcolumn.DataStyle.NumberFormat.Format = "#,##0"; + addedcolumn.TotalsRowStyle.NumberFormat.Format = "#,##0"; + + tbl1.ShowLastColumn = true; + + tbl1.Range.AutoFitColumns(); + + //Calculate the formulas so we get the calculated column values as well. + ws.Calculate(); + + //Create a data table from the table + var dataTable = tbl1.ToDataTable(x => { x.DataTableName = "DataTable1"; x.SkipNumberOfRowsEnd=2; }); + //Then create a new table from the data table + var range2=ws.Cells["K1"].LoadFromDataTable(dataTable, true, TableStyles.Dark4); + var tbl2 = ws.Tables.GetFromRange(range2); + + //Format the OrderDate column and add a Count Numbers subtotal. + tbl2.Columns["OrderDate"].TotalsRowFunction = RowFunctions.CountNums; + tbl2.Columns["OrderDate"].DataStyle.NumberFormat.Format = "yyyy-MM-dd"; + tbl2.Columns["OrderDate"].TotalsRowStyle.NumberFormat.Format = "#,##0"; + + //Format the OrderValue column and add a Sum subtotal. + tbl2.Columns["OrderValue"].TotalsRowFunction = RowFunctions.Sum; + tbl2.Columns["OrderValue"].DataStyle.NumberFormat.Format = "#,##0"; + tbl2.Columns["OrderValue"].TotalsRowStyle.NumberFormat.Format = "#,##0"; + + range2.AutoFitColumns(); + } + /// + /// This sample creates a two table and a custom table style. The first table is styled using different style objects of the table. + /// The second table is styled using the custom table style + /// + /// + /// + /// + private static async Task StyleTablesAsync(string connectionString, ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("StyleTables"); + + var range1 = await LoadDataAsync(connectionString, ws).ConfigureAwait(false); + + //Add the table and set some styles and properties. + var tbl1 = ws.Tables.Add(range1, "StyleTable1"); + tbl1.TableStyle = TableStyles.Medium24; + tbl1.DataStyle.Font.Size = 10; + tbl1.Columns["E-Mail"].DataStyle.Font.Underline=OfficeOpenXml.Style.ExcelUnderLineType.Single; + tbl1.HeaderRowStyle.Font.Italic = true; + tbl1.ShowTotal = true; + tbl1.TotalsRowStyle.Font.Italic = true; + tbl1.Range.Style.Font.Name = "Arial"; + tbl1.Range.AutoFitColumns(); + + //Add two rows at the end. + var addedRange = tbl1.AddRow(2); + addedRange.Offset(0, 0, 1, 1).Value = "Added Row 1"; + addedRange.Offset(1, 0, 1, 1).Value = "Added Row 2"; + + //Add a custom formula to display number of items in the CompanyName column + tbl1.Columns[0].TotalsRowFormula= "\"Total Count is \" & SUBTOTAL(103,StyleTable1[CompanyName])"; + tbl1.Columns[0].TotalsRowStyle.Font.Color.SetColor(Color.Red); + + //We create a custom named style via the Workbook.Styles object. For more samples on custom styles see sample 27 + var customStyleName = "EPPlus Created Style"; + var customStyle = p.Workbook.Styles.CreateTableStyle(customStyleName, TableStyles.Medium13); + customStyle.HeaderRow.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + customStyle.FirstColumn.Style.Fill.BackgroundColor.SetColor(eThemeSchemeColor.Accent5); + customStyle.FirstColumn.Style.Fill.BackgroundColor.Tint=0.3; + customStyle.FirstColumn.Style.Font.Color.SetColor(eThemeSchemeColor.Text1); + + var range2 = await LoadDataAsync(connectionString, ws, "K1").ConfigureAwait(false); + var tbl2 = ws.Tables.Add(range2, "StyleTable2"); + //To apply the custom style we set the StyleName property to the name we choose for our style. + tbl2.StyleName = customStyleName; + tbl2.ShowFirstColumn = true; + + tbl2.Range.AutoFitColumns(); + } + /// + /// This sample creates a table and a slicer. + /// + /// The connection string to the database + /// The package + /// + private static async Task CreateTableFilterAndSlicerAsync(string connectionString, ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("Slicer"); + + var range = await LoadDataAsync(connectionString, ws).ConfigureAwait(false); + var tbl = ws.Tables.Add(range, "FilterTable1"); + tbl.TableStyle = TableStyles.Medium1; + + //Add a slicer and filter on company name. A table slicer is connected to a table columns value filter. + var slicer1 = tbl.Columns[0].AddSlicer(); + slicer1.FilterValues.Add("Cremin-Kihn"); + slicer1.FilterValues.Add("Senger LLC"); + range.AutoFitColumns(); + + //Apply the column filter, otherwise the slicer may be hidden when the filter is applied. + tbl.AutoFilter.ApplyFilter(); + slicer1.SetPosition(2, 0, 10, 0); + + //For more samples on filters and slicers see Sample 13 and 24. + } + private static async Task LoadDataAsync(string connectionString, ExcelWorksheet ws, string startCell="A1") + { + ExcelRangeBase range; + //Lets connect to the sample database for some data + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select companyname as CompanyName, [name] as [Name], Email as [E-Mail], c.Country as Country, o.orderid as OrderId, orderdate as OrderDate, ordervalue as OrderValue, currency as Currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + using (var sqlReader = sqlCmd.ExecuteReader()) + { + range = await ws.Cells[startCell].LoadFromDataReaderAsync(sqlReader, true); + } + } + sqlConn.Close(); + } + return range; + } + } +} diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 27ab0ad..415b2d4 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,11 +42,11 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.5.0\lib\net45\EPPlus.dll + + packages\EPPlus.5.5.5.529-20210311-develop\lib\net45\EPPlus.dll - - packages\Microsoft.IO.RecyclableMemoryStream.1.3.6\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll + + packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll @@ -115,6 +115,7 @@ + @@ -123,6 +124,8 @@ + + @@ -161,6 +164,8 @@ + + PreserveNewest diff --git a/Readme.md b/Readme.md index feee8d1..2ffe6a2 100644 --- a/Readme.md +++ b/Readme.md @@ -32,6 +32,8 @@ The solution can be opened in Visual Studio for Windows. |24|[Slicers](/24-Slicers/)|Sample showing how to add Pivot Table slicers and Tabel slicers |25|[Export to/from DataTable](/25-ImportAndExportDataTable)|Sample showing import/export rangedata with System.Data.DataTable |26|[Form controls](/26-FormControls)|Sample showing how to add differnt form controls and how to group drawings. +|27|[Custom styles for tables and slicers](/27-CustomNamedStyles)|Sample showing how to create custom styles from tables, pivot tables and slicers. +|28|[Tables](/28-Tables)|Sample showing how to work with tables. ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. diff --git a/Sample_Main.cs b/Sample_Main.cs index b15d455..ebbf4d3 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -166,8 +166,10 @@ await ChartsAndThemesSample.RunAsync(connectionStr, Console.WriteLine(); //Sample 18 - Pivottables - Console.WriteLine("Running sample 18"); - output = PivotTablesSample.Run(connectionStr); //TODO: Fix database + //This sample demonstrates how to create and work with pivot tables. + output = PivotTablesSample.Run(connectionStr); + //The second class demonstrates how to style you pivot table. + PivotTablesStylingSample.Run(); Console.WriteLine("Sample 18 created {0}", output); Console.WriteLine(); @@ -220,6 +222,18 @@ await ChartsAndThemesSample.RunAsync(connectionStr, FormControlsSample.Run(); Console.WriteLine("Sample 26 finished."); Console.WriteLine(); + + //Sample 27 - Custom Named Table, Pivot Table and Slicer styles + Console.WriteLine("Running sample 27 - Custom table and slicer styles"); + CustomTableSlicerStyleSample.Run(connectionStr); + Console.WriteLine("Sample 27 finished."); + Console.WriteLine(); + + //Sample 27 - Custom Named Table, Pivot Table and Slicer styles + Console.WriteLine("Running sample 28 - Working with tables"); + await TablesSample.RunAsync(connectionStr); + Console.WriteLine("Sample 28 finished."); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index c703d8e..ea0379b 100644 --- a/packages.config +++ b/packages.config @@ -1,8 +1,8 @@  - - + + From 221b7eb0e143be43058b779b43a7e4030c54356f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Mon, 15 Mar 2021 11:18:08 +0100 Subject: [PATCH 08/18] Changed to EPPlus 5.6 nuget package --- EPPlus.Sample.NET.csproj | 4 ++-- packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 415b2d4..8eb2456 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,8 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.5.5.529-20210311-develop\lib\net45\EPPlus.dll + + packages\EPPlus.5.6.0\lib\net45\EPPlus.dll packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll diff --git a/packages.config b/packages.config index ea0379b..3338751 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - + From 490d0b2c240a9dfd3a97f07ec6f339e065ec1d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Thu, 17 Jun 2021 14:22:09 +0200 Subject: [PATCH 09/18] Samples for EPPlus 5.7 --- 18-PivotTables/PivotTablesSample.cs | 97 ++++++++++- 18-PivotTables/PivotTablesStylingSample.cs | 66 ++++++++ 29-ExternalLinks/Data/DataFile.xlsx | Bin 0 -> 12196 bytes 29-ExternalLinks/ExternalLinksSample.cs | 160 ++++++++++++++++++ 29-ExternalLinks/Readme.md | 9 + .../WorkbookWithExternalLinks.xlsx | Bin 0 -> 16450 bytes 30-SortingRanges/Readme.md | 5 + 30-SortingRanges/SortingRangesSample.cs | 83 +++++++++ EPPlus.Sample.NET.csproj | 10 +- Readme.md | 30 +++- Sample_Main.cs | 12 ++ packages.config | 2 +- 12 files changed, 467 insertions(+), 7 deletions(-) create mode 100644 29-ExternalLinks/Data/DataFile.xlsx create mode 100644 29-ExternalLinks/ExternalLinksSample.cs create mode 100644 29-ExternalLinks/Readme.md create mode 100644 29-ExternalLinks/WorkbookWithExternalLinks.xlsx create mode 100644 30-SortingRanges/Readme.md create mode 100644 30-SortingRanges/SortingRangesSample.cs diff --git a/18-PivotTables/PivotTablesSample.cs b/18-PivotTables/PivotTablesSample.cs index 3f5aa8c..5bb9d96 100644 --- a/18-PivotTables/PivotTablesSample.cs +++ b/18-PivotTables/PivotTablesSample.cs @@ -69,14 +69,17 @@ orderby s.Name var pt3 = CreatePivotTableWithPageFilter(pck, pt2.CacheDefinition); var pt4 = CreatePivotTableWithASlicer(pck, pt2.CacheDefinition); var pt5 = CreatePivotTableWithACalculatedField(pck, pt2.CacheDefinition); - - //Filter samples var pt6 = CreatePivotTableCaptionFilter(pck, dataRange); + var pt7 = CreatePivotTableWithDataFieldsUsingShowAs(pck, dataRange); + + CreatePivotTableSorting(pck, dataRange); pck.Save(); } return newFile.FullName; } + + private static ExcelPivotTable CreatePivotTableWithPivotChart(ExcelPackage pck, ExcelRangeBase dataRange) { var wsPivot = pck.Workbook.Worksheets.Add("PivotSimple"); @@ -273,6 +276,96 @@ private static ExcelPivotTable CreatePivotTableCaptionFilter(ExcelPackage pck, E pivotTable4.DataOnRows = false; return pivotTable4; } + private static ExcelPivotTable CreatePivotTableWithDataFieldsUsingShowAs(ExcelPackage pck, ExcelRangeBase dataRange) + { + var wsPivot5 = pck.Workbook.Worksheets.Add("PivotWithShowAsFields"); + + //Create a new pivot table with a new cache. + var pivotTable5 = wsPivot5.PivotTables.Add(wsPivot5.Cells["A3"], dataRange, "WithCaptionFilter"); + + var rowField1 = pivotTable5.RowFields.Add(pivotTable5.Fields["CompanyName"]); + var rowField2 = pivotTable5.RowFields.Add(pivotTable5.Fields["Name"]); + var colField1 = pivotTable5.ColumnFields.Add(pivotTable5.Fields["Currency"]); + + //Collapses all row and column fields + rowField1.Items.Refresh(); + rowField1.Items.ShowDetails(false); + + rowField2.Items.Refresh(); + rowField2.Items.ShowDetails(false); + + colField1.Items.Refresh(); + colField1.Items.ShowDetails(false); + + //Sets the ∑ Values position within column or row fields collection. + //The value of the pivotTable5.DataOnRows will determin if the rowFields or columnsFields collection is used. + //A negative or out of range value will add the values to the end of the collection. + pivotTable5.DataOnRows = false; + pivotTable5.ValuesFieldPosition = 0; //Set values first in the row fields collection + + var df1 = pivotTable5.DataFields.Add(pivotTable5.Fields["OrderValue"]); + df1.Name = "Order value"; + df1.Format = "#,##0"; + + var df2 = pivotTable5.DataFields.Add(pivotTable5.Fields["OrderValue"]); + df2.Name = "Order value % of total"; + df2.ShowDataAs.SetPercentOfColumn(); + df2.Format = "0.0%;"; + + var df3 = pivotTable5.DataFields.Add(pivotTable5.Fields["OrderValue"]); + df3.Name = "Count Difference From Previous"; + df3.ShowDataAs.SetDifference(rowField1, ePrevNextPivotItem.Previous); + df3.Function = DataFieldFunctions.Count; + df3.Format = "#,##0"; + + pivotTable5.SetCompact(false); + pivotTable5.ColumnHeaderCaption = "Data"; + pivotTable5.ShowColumnStripes = true; + wsPivot5.Column(1).Width = 30; + + return pivotTable5; + } + private static void CreatePivotTableSorting(ExcelPackage pck, ExcelRangeBase dataRange) + { + var wsPivot = pck.Workbook.Worksheets.Add("PivotSorting"); + + //Sort by the row field + var pt1 = wsPivot.PivotTables.Add(wsPivot.Cells["A1"], dataRange, "PerCountrySorted"); + pt1.DataOnRows = true; + + var rowField1 = pt1.RowFields.Add(pt1.Fields["Country"]); + rowField1.Sort = eSortType.Ascending; + var dataField = pt1.DataFields.Add(pt1.Fields["OrderValue"]); + dataField.Format = "#,##0"; + + + //Sort by the datafield field + var pt2 = wsPivot.PivotTables.Add(wsPivot.Cells["D1"], dataRange, "PerCountrySortedByData"); + pt2.DataOnRows = true; + + rowField1 = pt2.RowFields.Add(pt2.Fields["Country"]); + dataField = pt2.DataFields.Add(pt2.Fields["OrderValue"]); + dataField.Format = "#,##0"; + rowField1.SetAutoSort(dataField, eSortType.Descending); + + + //Sort by the data field for a specific column using pivot areas. + //In this case we sort on the order value column for "Poland". + var pt3 = wsPivot.PivotTables.Add(wsPivot.Cells["G1"], dataRange, "PerCountrySortedByDataColumn"); + pt3.DataOnRows = true; + + rowField1 = pt3.RowFields.Add(pt3.Fields["Name"]); + var columnField1 = pt3.ColumnFields.Add(pt3.Fields["Country"]); + dataField = pt3.DataFields.Add(pt3.Fields["OrderValue"]); + dataField.Format = "#,##0"; + rowField1.SetAutoSort(dataField, eSortType.Ascending); + + var conditionField = rowField1.AutoSort.Conditions.Fields.Add(columnField1); + //Before setting a reference to a value column we need to refresh the items cache. + columnField1.Items.Refresh(); + conditionField.Items.AddByValue("Poland"); + } + private static List GetDataFromSQL(string connectionStr) { var ret = new List(); diff --git a/18-PivotTables/PivotTablesStylingSample.cs b/18-PivotTables/PivotTablesStylingSample.cs index 2252cf2..8518bd7 100644 --- a/18-PivotTables/PivotTablesStylingSample.cs +++ b/18-PivotTables/PivotTablesStylingSample.cs @@ -53,11 +53,41 @@ public static string Run() //Sets the pivot table into tabular mode to display the filter boxes on the row fields then styles the button fields StylePivotTable6_CaptionFilter(pck); + //Sets column fields to different background colors. + StylePivotTable7_WithDataFieldsUsingShowAs(pck); + + StylePivotTable8_Sort(pck); pck.Save(); } return newFile.FullName; } + private static void StylePivotTable8_Sort(ExcelPackage pck) + { + var wsPivot = pck.Workbook.Worksheets["PivotSorting"]; + + //Mark the sorted ranges + var pt1 = wsPivot.PivotTables[0]; + var style1 = pt1.Styles.AddLabel(pt1.RowFields[0]); + style1.Style.Border.BorderAround(ExcelBorderStyle.DashDotDot,Color.Red); + + //Set color red for data cells q + var pt2 = wsPivot.PivotTables[1]; + var style2 = pt2.Styles.AddAllData(); + style2.GrandColumn = true; + style2.Style.Font.Color.SetColor(Color.Red); + + //Mark sorted column with value "Poland" + var pt3 = wsPivot.PivotTables[2]; + var style3 = pt3.Styles.AddData(pt3.RowFields[0]); //Add style for Row field "Name" + style3.Conditions.DataFields.Add(pt3.DataFields[0]); //..then add a condition for data field "Order Value" and... + var conditions = style3.Conditions.Fields.Add(pt3.ColumnFields[0]); //...column field Country with value... + //pt3.ColumnFields[0].Items.Refresh(); + conditions.Items.AddByValue("Poland"); //..."Poland"".. + style3.Style.Font.Color.SetColor(Color.Green); + + } + private static void StylePivotTable1_PerCountry(ExcelPackage pck) { var pivot1 = pck.Workbook.Worksheets["PivotSimple"].PivotTables[0]; @@ -240,5 +270,41 @@ private static void StylePivotTable6_CaptionFilter(ExcelPackage pck) var style2 = pivotTable6.Styles.AddButtonField(ePivotTableAxis.RowAxis, 1); //Field with index 1 in the row axis. style2.Style.Font.Color.SetColor(eThemeSchemeColor.Accent4); } + private static void StylePivotTable7_WithDataFieldsUsingShowAs(ExcelPackage pck) + { + var wsPivot7 = pck.Workbook.Worksheets["PivotWithShowAsFields"]; + var pivotTable7 = wsPivot7.PivotTables[0]; + + pivotTable7.PivotTableStyle = PivotTableStyles.Dark18; + + var styleUSD=pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleUSD.Conditions.Fields[0].Items.AddByValue("USD"); + styleUSD.Style.Fill.PatternType = ExcelFillStyle.Solid; + styleUSD.Style.Fill.BackgroundColor.Tint = -0.9; + + var styleEUR = pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleEUR.Conditions.Fields[0].Items.AddByValue("EUR"); + styleEUR.Style.Fill.PatternType = ExcelFillStyle.Solid; + styleEUR.Style.Fill.BackgroundColor.Tint = -0.85; + + var styleSEK = pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleSEK.Conditions.Fields[0].Items.AddByValue("SEK"); + styleSEK.Style.Fill.PatternType = ExcelFillStyle.Solid; + styleSEK.Style.Fill.BackgroundColor.Tint = -0.80; + + var styleDKK = pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleDKK.Conditions.Fields[0].Items.AddByValue("DKK"); + styleDKK.Style.Fill.PatternType = ExcelFillStyle.Solid; + styleDKK.Style.Fill.BackgroundColor.Tint = -0.75; + + var styleINR = pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleINR.Conditions.Fields[0].Items.AddByValue("INR"); + styleINR.Style.Fill.PatternType = ExcelFillStyle.Solid; + styleINR.Style.Fill.BackgroundColor.Tint = -0.70; + + var styleTotal = pivotTable7.Styles.AddData(pivotTable7.Fields["Currency"]); + styleTotal.GrandRow = true; + styleTotal.Style.Fill.BackgroundColor.Tint = -1; + } } } diff --git a/29-ExternalLinks/Data/DataFile.xlsx b/29-ExternalLinks/Data/DataFile.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..96fdc57309f33625723672eec251229901571e97 GIT binary patch literal 12196 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 literal 0 HcmV?d00001 diff --git a/29-ExternalLinks/ExternalLinksSample.cs b/29-ExternalLinks/ExternalLinksSample.cs new file mode 100644 index 0000000..cd5e9e6 --- /dev/null +++ b/29-ExternalLinks/ExternalLinksSample.cs @@ -0,0 +1,160 @@ +using OfficeOpenXml; +using OfficeOpenXml.ExternalReferences; +using System; +using System.IO; +namespace EPPlusSamples +{ + /// + /// This sample demonstrates how work with External references in EPPlus. + /// EPPlus supports adding, updating and removing external workbooks of type xlsx, xlsm and xlst. EPPlus also use the external reference cache for External workbooks. + /// EPPlus will also preserve DDE and OLE links. + /// + public static class ExternalLinksSample + { + public static void Run() + { + //Reads a workbook and calculates the formulas from the cache and from the loaded external workbook. + ReadFileWithExternalLink(); + + //Sample file 1 adds external links to another workbook. + var sampleFile1 = FileOutputUtil.GetFileInfo("29-ExternalLinks-1.xlsx"); + using (var p = new ExcelPackage(sampleFile1)) + { + + AddWorksheetWithExternalReferences(p); + + AddWorksheetWithExternalReferencesInFormulas(p); + + p.Save(); + } + + //Open the saved sample and break links to the fist external workbook + BreakLinks(sampleFile1); + } + + + /// + /// This sample shows how EPPlus works with external workbooks depending on + /// + private static void ReadFileWithExternalLink() + { + var externalFile = FileInputUtil.GetFileInfo("29-ExternalLinks", "WorkbookWithExternalLinks.xlsx"); + using (var p = new ExcelPackage(externalFile)) + { + //This worksheet contains references to an external workbook. + //First print the values saved in the package. + var ws = p.Workbook.Worksheets[0]; + Console.WriteLine("Values from Excel:"); + Console.WriteLine($"Cell C1 formula : {ws.Cells["C1"].Formula} with value {ws.Cells["C1"].Value}"); + Console.WriteLine($"Cell C2 formula : {ws.Cells["C2"].Formula} with value {ws.Cells["C2"].Value}"); + Console.WriteLine($"Cell C3 formula : {ws.Cells["C3"].Formula} with value {ws.Cells["C3"].Value}"); + Console.WriteLine($"Cell C5 formula : {ws.Cells["C5"].Formula} with value {ws.Cells["C5"].Text}"); + Console.WriteLine($"Cell C6 formula : {ws.Cells["C6"].Formula} with value {ws.Cells["C6"].Value}"); + Console.WriteLine(); + + //Now, clear the formula values and calculate the workbook again. + //In this case, EPPlus uses the package internal saved cache for the external workbook to calculate the formulas referencing this workbook. + ws.ClearFormulaValues(); + ws.Calculate(); + + Console.WriteLine("Values after calculation in EPPLus from external reference cache:"); + Console.WriteLine($"Cell C1 formula : {ws.Cells["C1"].Formula} with value {ws.Cells["C1"].Value}"); + Console.WriteLine($"Cell C2 formula : {ws.Cells["C2"].Formula} with value {ws.Cells["C2"].Value}"); + Console.WriteLine($"Cell C3 formula : {ws.Cells["C3"].Formula} with value {ws.Cells["C3"].Value}"); + Console.WriteLine($"Cell C5 formula : {ws.Cells["C5"].Formula} with value {ws.Cells["C5"].Text}"); + Console.WriteLine($"Cell C6 formula : {ws.Cells["C6"].Formula} with value {ws.Cells["C6"].Value}"); + Console.WriteLine(); + + //Note in the output, that Cell C6 has a different value from the Excel Calculation. + //This is because the saved cache does not contain all information required, in this case some of the lines are hidden and should be ignored by the subtotal function. + //This is the same behavior as in Excel if you recalculate without the external workbook available. + + //To avoid this behavior you can load the external workbook before doing the calculate. + //This is only an issue in special cases where the function needs information not available in the cache, as for example hidden cells and numeric formats. + var externalReference = p.Workbook.ExternalLinks[0].As.ExternalWorkbook; + p.Workbook.ExternalLinks.Directories.Add(FileInputUtil.GetSubDirectory("29-ExternalLinks","Data")); + externalReference.Load(); + + ws.ClearFormulaValues(); + ws.Calculate(); + + Console.WriteLine("Values after calculation in EPPLus when the external package has been loaded:"); + Console.WriteLine($"Cell C1 formula : {ws.Cells["C1"].Formula} with value {ws.Cells["C1"].Value}"); + Console.WriteLine($"Cell C2 formula : {ws.Cells["C2"].Formula} with value {ws.Cells["C2"].Value}"); + Console.WriteLine($"Cell C3 formula : {ws.Cells["C3"].Formula} with value {ws.Cells["C3"].Value}"); + Console.WriteLine($"Cell C5 formula : {ws.Cells["C5"].Formula} with value {ws.Cells["C5"].Text}"); + Console.WriteLine($"Cell C6 formula : {ws.Cells["C6"].Formula} with value {ws.Cells["C6"].Value}"); + Console.WriteLine(); + } + } + + private static void AddWorksheetWithExternalReferences(ExcelPackage p) + { + //Add a reference to the file created by sample 28. + var externalLinkFile = FileOutputUtil.GetFileInfo("28-Tables.xlsx", false); + var externalWorkbook = p.Workbook.ExternalLinks.AddExternalWorkbook(externalLinkFile); + + var ws = p.Workbook.Worksheets.Add("Sheet1"); + //You can access individual cells like this using the index of the external reference in brackets... + //[1] reference to the the first item in the ExternalReferences collection. This is the externalWorkbook. Index property + ws.Cells["A1:C3"].Formula = "[1]SimpleTable!A1"; + + //You can also reference a value and set a format. Here we use the index property instead of hardcoding it in the formula. + ws.Cells["F1"].Formula = $"[{externalWorkbook.Index}]Slicer!F38"; + ws.Cells["F1"].Style.Numberformat.Format = "yyyy-MM-dd"; + + //Now, Calculate. As the workbook is loaded EPPlus will use the actual values in the package. + ws.Calculate(); + + //The cache stores cell values that are referenced when calculating formulas in the workbook, so formulas can be calculated without access to the external workbook. + externalWorkbook.UpdateCache(); + var f38Value = externalWorkbook.CachedWorksheets["Slicer"].CellValues["F38"].Value; + Console.WriteLine($"Value of cached value in {externalWorkbook.File.Name} worksheet Slicer cell F38 is : {f38Value}"); + + ws.Cells.AutoFitColumns(); + Console.WriteLine($"Cell F1 with an external link has value: {ws.Cells["F1"].Value} - formatted: {ws.Cells["F1"].Text}"); + } + private static void AddWorksheetWithExternalReferencesInFormulas(ExcelPackage p) + { + var externalLinkFile = FileOutputUtil.GetFileInfo("01-GettingStarted.xlsx", false); + var externalWorkbook = p.Workbook.ExternalLinks.AddExternalWorkbook(externalLinkFile); + + var ws = p.Workbook.Worksheets.Add("Sheet2"); + + ws.Cells["A1"].Value = "Quantity*Price:"; + ws.Cells["B1:B3"].Formula = "[2]Inventory!C2*[2]Inventory!D2"; //Here we reference the second external reference, so index is [2] + + ws.Cells["B4"].Formula = "Sum(B1:B3)"; + ws.Cells["C4"].Formula = "[2]Inventory!E5"; + + ws.Cells["A4"].Value = "SUM:"; + ws.Cells["A4"].AddComment("Sum of external cells matches the sum from cell E5 in the original workbook", "EPPlus Software"); + ws.Cells["B4:C4"].Style.Font.Bold = true; + ws.Cells["B4:C4"].Style.Numberformat.Format = "#,##0"; + + ws.Calculate(); + + //If you only want to update the cache you can use externalWorkbook.UpdateCache(); + //Note: The cache is updated when the package is saved if externalWorkbook.CacheStatue is eExternalWorkbookCacheStatus.NotUpdated. + // If the cache status is LoadedFromPackage or Updated, you must make sure to update the cache, if necessary, before saving the packge. + externalWorkbook.UpdateCache(); + + ws.Cells.AutoFitColumns(); + } + private static void BreakLinks(FileInfo sampleFile1) + { + //If you want to break links to a workbook, you simply remove it from the ExteralLinks collection. + //This will remove any formulas referencing the workbook and leave the values in the cells. Defined names referencing an external workbook will be set to #REF! + + using(var p=new ExcelPackage(sampleFile1)) + { + Console.WriteLine($"Now break links to the workbook {p.Workbook.ExternalLinks[0].As.ExternalWorkbook.File.FullName}"); + p.Workbook.ExternalLinks.RemoveAt(0); + + var newFile = FileOutputUtil.GetFileInfo("29-ExternalLinks-Link1Removed.xlsx", false); + p.SaveAs(newFile); + } + } + + } +} diff --git a/29-ExternalLinks/Readme.md b/29-ExternalLinks/Readme.md new file mode 100644 index 0000000..1efef53 --- /dev/null +++ b/29-ExternalLinks/Readme.md @@ -0,0 +1,9 @@ +# 29 - External references +This example shows how to work with external links to other workbooks. +EPPlus uses the external workbook cache when calculating formulas. +The external workbook can also be loaded to update the cache or calculate use values directly from the external workbook. +EPPlus also loads and preserves DDE and OLE links. +### [ExternalLinksSample.cs](ExternalLinkssSample.cs) + +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/29-ExternalLinks/WorkbookWithExternalLinks.xlsx b/29-ExternalLinks/WorkbookWithExternalLinks.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e32f47f11040fe0944c9a37ab174c135268476b8 GIT binary patch literal 16450 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 literal 0 HcmV?d00001 diff --git a/30-SortingRanges/Readme.md b/30-SortingRanges/Readme.md new file mode 100644 index 0000000..9fcc681 --- /dev/null +++ b/30-SortingRanges/Readme.md @@ -0,0 +1,5 @@ +# 30 - Sorting ranges +These samples demonstrates how to sort ranges with EPPlus. Contains one example for sorting top to bottom and one for left to right using a custom list. +### [SortingRangesSample.cs](SortingRangesSample.cs) +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/30-SortingRanges/SortingRangesSample.cs b/30-SortingRanges/SortingRangesSample.cs new file mode 100644 index 0000000..1c199ce --- /dev/null +++ b/30-SortingRanges/SortingRangesSample.cs @@ -0,0 +1,83 @@ +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + /// + /// This sample demonstrates how to sort ranges with EPPlus. + /// + public static class SortingRangesSample + { + private static string[] _letters = new string[] { "A", "B", "C", "D" }; + private static string[] _tShirtSizes = new string[] { "S", "M", "L", "XL", "XXL" }; + private const int StartRow = 3; + public static void Run() + { + using (var p = new ExcelPackage()) + { + CreateWorksheetsAndLoadData(p); + var sheet1 = p.Workbook.Worksheets[0]; + var sheet2 = p.Workbook.Worksheets[1]; + // Sort the range by column 0, then by column 1 descending + sheet1.Cells["A3:D17"].Sort(x => x.SortBy.Column(0).ThenSortBy.Column(1, eSortOrder.Descending)); + + // Sort the range left to right by row 0 (using a custom list), then by row 1 + sheet2.Cells["A3:K5"].Sort(x => x.SortLeftToRightBy.Row(0).UsingCustomList("S", "M", "L", "XL", "XXL").ThenSortBy.Row(1)); + + p.SaveAs(FileOutputUtil.GetFileInfo("30-SortingRanges.xlsx")); + } + } + + private static void CreateWorksheetsAndLoadData(ExcelPackage p) + { + var rnd = new Random((int)DateTime.UtcNow.ToOADate()); + + var sheet1 = p.Workbook.Worksheets.Add("Sort top down"); + sheet1.Cells["A1"].Value = "To view the sort state in Excel 2019 with english localization, select the range A3:D17, right click and chose 'Sort' followed by 'Custom sort'"; + // create random data for this sheet + for(var row = StartRow; row < (StartRow + 15); row++) + { + for(var col = 1; col < 5; col++) + { + if(col == 1) + { + var ix = rnd.Next(0, _letters.Length - 1); + sheet1.Cells[row, 1].Value = _letters[ix]; + } + else if(col == 4) + { + // Add a formula in the right most column to demonstrate that the formulas will be shifted when sorted. + sheet1.Cells[row, 4].Formula = $"SUM(B{row}:C{row})"; + } + else + { + sheet1.Cells[row, col].Value = rnd.Next(14, 555); + } + } + } + + var sheet2 = p.Workbook.Worksheets.Add("Sort left to right"); + sheet2.Cells["A1"].Value = "To view the sort state in Excel 2019 with english localization, select the range A3:K5, right click and chose 'Sort' followed by 'Custom sort'"; + // create random data for this sheet + for (var col = 1; col < 12; col++) + { + for (var row = 3; row < 6; row++) + { + if (row == 3) + { + var ix = rnd.Next(0, _tShirtSizes.Length - 1); + sheet2.Cells[row, col].Value = _tShirtSizes[ix]; + sheet2.Cells[row, col].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right; + } + else + { + sheet2.Cells[row, col].Value = rnd.Next(14, 555); + } + } + } + } + } +} diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 8eb2456..474ea9a 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,8 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.6.0\lib\net45\EPPlus.dll + + packages\EPPlus.5.7.0\lib\net45\EPPlus.dll packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll @@ -126,6 +126,8 @@ + + @@ -166,6 +168,10 @@ + + + + PreserveNewest diff --git a/Readme.md b/Readme.md index 2ffe6a2..644cbed 100644 --- a/Readme.md +++ b/Readme.md @@ -1,8 +1,15 @@ # EPPlus samples -### EPPlus samples for .NET Framework +### EPPlus samples for .Net Core -The solution can be opened in Visual Studio for Windows. +The solution can be opened in Visual Studio for Windows or MacOS. On other operating systems please use... + +``` +dotnet restore +dotnet run +``` + +... to execute the samples. |No|Sample|Description| |---|---|-----------------| @@ -34,8 +41,27 @@ The solution can be opened in Visual Studio for Windows. |26|[Form controls](/26-FormControls)|Sample showing how to add differnt form controls and how to group drawings. |27|[Custom styles for tables and slicers](/27-CustomNamedStyles)|Sample showing how to create custom styles from tables, pivot tables and slicers. |28|[Tables](/28-Tables)|Sample showing how to work with tables. +|29|[External links](/29-ExternalLinks)|Shows how to work with links to external workbooks +|30|[Sorting Ranges](/30-SortingRanges)|Shows how to work with the Sort method for ranges and tables ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. + +### Non windows operating systems. +Non-windows operating systems will requires libgdiplus to be installed. +Please use your favorite package manager to install it. +For example: + +Homebrew on MacOS: +``` +brew install mono-libgdiplus +``` + +apt-get: +``` +apt-get install libgdiplus +``` +For Docker, see our [Docker file samples]( https://github.com/EPPlusSoftware/EPPlus/wiki/EPPlus-and-Docker) + Also see wiki on https://github.com/EPPlusSoftware/EPPlus/wiki for more details diff --git a/Sample_Main.cs b/Sample_Main.cs index ebbf4d3..8d04802 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -234,6 +234,18 @@ await ChartsAndThemesSample.RunAsync(connectionStr, await TablesSample.RunAsync(connectionStr); Console.WriteLine("Sample 28 finished."); Console.WriteLine(); + + //Sample 29 - Add references to external workbooks + Console.WriteLine("Running sample 29 - External Links"); + ExternalLinksSample.Run(); + Console.WriteLine("Sample 29 finished."); + Console.WriteLine(); + + // Sample 30 - Sort ranges + Console.WriteLine("Running sample 30 - Sort ranges"); + SortingRangesSample.Run(); + Console.WriteLine("Sample 30 finished."); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index 3338751..1094c3c 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - + From 4af2bc5fc59d5411e062d41dfac002021dac80af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Tue, 10 Aug 2021 08:47:23 +0200 Subject: [PATCH 10/18] Removed .NET Core related instructions. --- Readme.md | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/Readme.md b/Readme.md index 644cbed..a047e66 100644 --- a/Readme.md +++ b/Readme.md @@ -1,15 +1,8 @@ # EPPlus samples -### EPPlus samples for .Net Core +### EPPlus samples for .NET Framework -The solution can be opened in Visual Studio for Windows or MacOS. On other operating systems please use... - -``` -dotnet restore -dotnet run -``` - -... to execute the samples. +The solution can be opened in Visual Studio for Windows. |No|Sample|Description| |---|---|-----------------| @@ -47,21 +40,4 @@ dotnet run ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. - -### Non windows operating systems. -Non-windows operating systems will requires libgdiplus to be installed. -Please use your favorite package manager to install it. -For example: - -Homebrew on MacOS: -``` -brew install mono-libgdiplus -``` - -apt-get: -``` -apt-get install libgdiplus -``` -For Docker, see our [Docker file samples]( https://github.com/EPPlusSoftware/EPPlus/wiki/EPPlus-and-Docker) - Also see wiki on https://github.com/EPPlusSoftware/EPPlus/wiki for more details From 22b8339f75ae2439a70fd1d6924ec8a0fb178270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E4=B8=89=E5=B0=8F=E4=BC=99=E5=84=BF?= <1790617178@qq.com> Date: Thu, 9 Sep 2021 11:43:44 +0800 Subject: [PATCH 11/18] Remove duplicate files --- 25-ImportAndExportDataTable/readme.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 25-ImportAndExportDataTable/readme.md diff --git a/25-ImportAndExportDataTable/readme.md b/25-ImportAndExportDataTable/readme.md deleted file mode 100644 index 44e8697..0000000 --- a/25-ImportAndExportDataTable/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# 25 - Import/export with DataTable -These samples demonstrates how to import and export data to/from a range to/from a DataTable. - -### [DataTableSample.cs](DataTableSample.cs) - ---- -[Back to overview](/Readme.md) \ No newline at end of file From 0669cced515dd1a20a7b6e2c08cc9550fe7e503f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Thu, 21 Oct 2021 16:29:14 +0200 Subject: [PATCH 12/18] EPPlus version 5.8.0 --- 01-GettingStarted/GettingStartedSample.cs | 6 +- 02-ReadWorkbook/ReadWorkbookSample.cs | 4 +- 03-UsingAsyncAwait/Readme.md | 2 +- 03-UsingAsyncAwait/UsingAsyncAwaitSample.cs | 6 +- ...LoadingDataFromCollectionWithAttributes.cs | 2 +- .../LoadingDataWithDynamicObjects.cs | 6 +- 04-LoadingData/LoadingDataWithTablesSample.cs | 4 +- .../ImportAndExportCsvFilesSample.cs | 12 +- .../CalculateExistingWorkbook.cs | 2 +- .../OpenWorkbookAndAddDataAndChart.cs | 4 +- 08-SalesReport/SalesReport.cs | 24 +- .../PerformanceAndProtectionSample.cs | 4 +- 10-ReadDataUsingLinq/ReadDataUsingLinq.cs | 2 +- .../ConditionalFormattingSample.cs | 2 +- 12-DataValidation/DataValidationSample.cs | 2 +- 13-Filter/FilterSample.cs | 2 +- 13-Filter/Readme.md | 5 +- 14-ShapesAndImages/ShapesAndImagesSample.cs | 12 +- 15-ChartsAndThemes/ChartTemplateSample.cs | 2 +- 15-ChartsAndThemes/ChartsAndThemes.cs | 393 ------------------ 15-ChartsAndThemes/ChartsAndThemesSample.cs | 11 +- .../ColumnChartsWithLegendSample.cs | 40 ++ 15-ChartsAndThemes/Readme.md | 2 +- 16-Sparklines/SparklinesSample.cs | 10 +- .../FXReportFromDatabase.cs | 10 +- 18-PivotTables/PivotTablesSample.cs | 10 +- 18-PivotTables/PivotTablesStylingSample.cs | 4 +- .../EncryptionAndProtectionSample.cs | 14 +- .../CreateAFileSystemReport.cs | 25 +- 21-VBA/WorkingWithVbaSample.cs | 14 +- 22-IgnoreErrors/IgnoreErrorsSample.cs | 2 +- 23-Comments/CommentsSample.cs | 4 +- 24-Slicers/SlicerSample.cs | 5 +- 26-FormControls/FormControlsSample.cs | 12 +- .../TableSlicerStyleSample.cs | 2 +- 28-Tables/Readme.md | 4 +- 28-Tables/SortingTablesSample.cs | 63 +++ 28-Tables/TablesSample.cs | 2 +- 29-ExternalLinks/ExternalLinksSample.cs | 12 +- 30-SortingRanges/Readme.md | 5 - 30-WorkingWithRanges/CopyRangeSample.cs | 127 ++++++ 30-WorkingWithRanges/FillRangeSample.cs | 168 ++++++++ 30-WorkingWithRanges/Readme.md | 10 + .../SortingRangesSample.cs | 2 +- EPPlus.Sample.NET.csproj | 14 +- FileInputUtil.cs | 50 --- FileOutputUtil.cs => FileUtil.cs | 47 ++- Sample_Main.cs | 44 +- packages.config | 2 +- 49 files changed, 606 insertions(+), 605 deletions(-) delete mode 100644 15-ChartsAndThemes/ChartsAndThemes.cs create mode 100644 15-ChartsAndThemes/ColumnChartsWithLegendSample.cs create mode 100644 28-Tables/SortingTablesSample.cs delete mode 100644 30-SortingRanges/Readme.md create mode 100644 30-WorkingWithRanges/CopyRangeSample.cs create mode 100644 30-WorkingWithRanges/FillRangeSample.cs create mode 100644 30-WorkingWithRanges/Readme.md rename {30-SortingRanges => 30-WorkingWithRanges}/SortingRangesSample.cs (97%) delete mode 100644 FileInputUtil.cs rename FileOutputUtil.cs => FileUtil.cs (60%) diff --git a/01-GettingStarted/GettingStartedSample.cs b/01-GettingStarted/GettingStartedSample.cs index 639c91d..562a798 100644 --- a/01-GettingStarted/GettingStartedSample.cs +++ b/01-GettingStarted/GettingStartedSample.cs @@ -24,7 +24,7 @@ class GettingStartedSample /// public static string Run() { - using (var package = new ExcelPackage()) + using (var package = new ExcelPackage()) { //Add a new worksheet to the empty workbook var worksheet = package.Workbook.Worksheets.Add("Inventory"); @@ -54,7 +54,7 @@ public static string Run() //Add a formula for the value-column worksheet.Cells["E2:E4"].Formula = "C2*D2"; - //Ok now format the values; + //Ok now format the values using (var range = worksheet.Cells[1, 1, 1, 5]) { range.Style.Font.Bold = true; @@ -110,7 +110,7 @@ public static string Run() package.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan Källman"); package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus"); - var xlFile = FileOutputUtil.GetFileInfo("01-GettingStarted.xlsx"); + var xlFile = FileUtil.GetCleanFileInfo("01-GettingStarted.xlsx"); // Save our new workbook in the output directory and we are done! package.SaveAs(xlFile); diff --git a/02-ReadWorkbook/ReadWorkbookSample.cs b/02-ReadWorkbook/ReadWorkbookSample.cs index 5428732..c915a21 100644 --- a/02-ReadWorkbook/ReadWorkbookSample.cs +++ b/02-ReadWorkbook/ReadWorkbookSample.cs @@ -23,12 +23,12 @@ class ReadWorkbookSample { public static void Run() { - var filePath = FileInputUtil.GetFileInfo("02-ReadWorkbook", "ReadWorkbook.xlsx").FullName; + var filePath = FileUtil.GetFileInfo("02-ReadWorkbook", "ReadWorkbook.xlsx").FullName; Console.WriteLine("Reading column 2 of {0}", filePath); Console.WriteLine(); FileInfo existingFile = new FileInfo(filePath); - using (ExcelPackage package = new ExcelPackage(existingFile)) + using (ExcelPackage package = new ExcelPackage(existingFile)) { //Get the first worksheet in the workbook ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; diff --git a/03-UsingAsyncAwait/Readme.md b/03-UsingAsyncAwait/Readme.md index 436b6df..dd09606 100644 --- a/03-UsingAsyncAwait/Readme.md +++ b/03-UsingAsyncAwait/Readme.md @@ -1,7 +1,7 @@ # 03 - Using async / await to load and save data This sample demonstrates how to load and save data using the async await pattern. -### [UsingAsyncAwait.cs](UsingAsyncAwaitSample.cs) +### [UsingAsyncAwaitSample.cs](UsingAsyncAwaitSample.cs) --- [Back to overview](/Readme.md) diff --git a/03-UsingAsyncAwait/UsingAsyncAwaitSample.cs b/03-UsingAsyncAwait/UsingAsyncAwaitSample.cs index 7210fd4..700ab64 100644 --- a/03-UsingAsyncAwait/UsingAsyncAwaitSample.cs +++ b/03-UsingAsyncAwait/UsingAsyncAwaitSample.cs @@ -30,7 +30,7 @@ class UsingAsyncAwaitSample /// The connection string to the SQLite database public static async Task RunAsync(string connectionString) { - var file = FileOutputUtil.GetFileInfo("03-AsyncAwait.xlsx"); + var file = FileUtil.GetCleanFileInfo("03-AsyncAwait.xlsx"); using (ExcelPackage package = new ExcelPackage(file)) { var ws = package.Workbook.Worksheets.Add("Sheet1"); @@ -54,10 +54,10 @@ public static async Task RunAsync(string connectionString) await package.LoadAsync(file); var newWs = package.Workbook.Worksheets.Add("AddedSheet2"); - var range = await newWs.Cells["A1"].LoadFromTextAsync(FileInputUtil.GetFileInfo("03-UsingAsyncAwait", "Importfile.txt"), new ExcelTextFormat { Delimiter='\t' }); + var range = await newWs.Cells["A1"].LoadFromTextAsync(FileUtil.GetFileInfo("03-UsingAsyncAwait", "Importfile.txt"), new ExcelTextFormat { Delimiter='\t' }); range.AutoFitColumns(); - await package.SaveAsAsync(FileOutputUtil.GetFileInfo("03-AsyncAwait-LoadedAndModified.xlsx")); + await package.SaveAsAsync(FileUtil.GetCleanFileInfo("03-AsyncAwait-LoadedAndModified.xlsx")); } } } diff --git a/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs index cffbc0b..aa88d37 100644 --- a/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs +++ b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs @@ -59,7 +59,7 @@ public static void Run() new Actor2{ Salary = 315.34, Tax = 0.28, FirstName = "Lisa", MiddleName = "Maria", LastName = "Gonzales", Birthdate = new DateTime(1971, 10, 2)} }; - using (var package = new ExcelPackage(FileOutputUtil.GetFileInfo("04-LoadFromCollectionAttributes.xlsx"))) + using (var package = new ExcelPackage(FileUtil.GetCleanFileInfo("04-LoadFromCollectionAttributes.xlsx"))) { // using the Actor class above var sheet = package.Workbook.Worksheets.Add("Actors"); diff --git a/04-LoadingData/LoadingDataWithDynamicObjects.cs b/04-LoadingData/LoadingDataWithDynamicObjects.cs index 1fcd659..d4002a2 100644 --- a/04-LoadingData/LoadingDataWithDynamicObjects.cs +++ b/04-LoadingData/LoadingDataWithDynamicObjects.cs @@ -52,7 +52,7 @@ public static void Run() }; // Create a workbook with a worksheet and load the data into a table - using(var package = new ExcelPackage(FileOutputUtil.GetFileInfo("04-LoadDynamicObjects.xlsx"))) + using(var package = new ExcelPackage(FileUtil.GetCleanFileInfo("04-LoadDynamicObjects.xlsx"))) { var sheet = package.Workbook.Worksheets.Add("Dynamic"); sheet.Cells["A1"].LoadFromDictionaries(items, c => @@ -69,8 +69,8 @@ public static void Run() } // Load data from json (in this case a file) - var jsonItems = JsonConvert.DeserializeObject>(File.ReadAllText(FileInputUtil.GetFileInfo("04-LoadingData", "testdata.json").FullName)); - using (var package = new ExcelPackage(FileOutputUtil.GetFileInfo("04-LoadJsonFromFile.xlsx"))) + var jsonItems = JsonConvert.DeserializeObject>(File.ReadAllText(FileUtil.GetFileInfo("04-LoadingData", "testdata.json").FullName)); + using (var package = new ExcelPackage(FileUtil.GetCleanFileInfo("04-LoadJsonFromFile.xlsx"))) { var sheet = package.Workbook.Worksheets.Add("Dynamic"); sheet.Cells["A1"].LoadFromDictionaries(jsonItems, c => diff --git a/04-LoadingData/LoadingDataWithTablesSample.cs b/04-LoadingData/LoadingDataWithTablesSample.cs index 31fe516..3625468 100644 --- a/04-LoadingData/LoadingDataWithTablesSample.cs +++ b/04-LoadingData/LoadingDataWithTablesSample.cs @@ -33,7 +33,7 @@ public static void Run() var pck = new ExcelPackage(); //Create a datatable with the directories and files from the current directory... - DataTable dt = GetDataTable(FileOutputUtil.GetDirectoryInfo(".")); + DataTable dt = GetDataTable(FileUtil.GetDirectoryInfo(".")); var wsDt = pck.Workbook.Worksheets.Add("FromDataTable"); @@ -108,7 +108,7 @@ orderby file.Name ascending wsList.Cells[wsList.Dimension.Address].AutoFitColumns(); //...and save - var fi = FileOutputUtil.GetFileInfo("04-LoadingData.xlsx"); + var fi = FileUtil.GetCleanFileInfo("04-LoadingData.xlsx"); pck.SaveAs(fi); pck.Dispose(); } diff --git a/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs b/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs index 15de020..b9f2a87 100644 --- a/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs +++ b/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs @@ -37,7 +37,7 @@ public static class ImportAndExportCsvFilesSample /// public static async Task Run() { - FileInfo newFile = FileOutputUtil.GetFileInfo(@"05-LoadDataFromCsvFilesIntoTables.xlsx"); + FileInfo newFile = FileUtil.GetCleanFileInfo(@"05-LoadDataFromCsvFilesIntoTables.xlsx"); using (ExcelPackage package = new ExcelPackage()) { @@ -60,7 +60,7 @@ private static async Task ExportTableAsync(ExcelPackage package) Encoding = new UTF8Encoding(), SkipLinesEnd=1 //Skip the totals row }; - await ws.Cells[tbl.Address.Address].SaveToTextAsync(FileOutputUtil.GetFileInfo("05-ExportedFromEPPlus.csv"), format); + await ws.Cells[tbl.Address.Address].SaveToTextAsync(FileUtil.GetCleanFileInfo("05-ExportedFromEPPlus.csv"), format); Console.WriteLine($"Writing the text file 'ExportedTable.csv'..."); } @@ -79,7 +79,7 @@ private static void LoadFile1(ExcelPackage package) SkipLinesEnd = 1 }; - var file1 = FileInputUtil.GetFileInfo("05-ImportAndExportCsvFiles", "Sample5-1.txt"); + var file1 = FileUtil.GetFileInfo("05-ImportAndExportCsvFiles", "Sample5-1.txt"); //Now read the file into the sheet. Start from cell A1. Create a table with style 27. First row contains the header. Console.WriteLine("Load the text file..."); @@ -150,7 +150,7 @@ private static async Task LoadFile2Async(ExcelPackage package) //Now read the file into the sheet. Console.WriteLine("Load the text file..."); - var file2 = FileInputUtil.GetFileInfo("05-ImportAndExportCsvFiles", "Sample5-2.txt"); + var file2 = FileUtil.GetFileInfo("05-ImportAndExportCsvFiles", "Sample5-2.txt"); var range = await sheet.Cells["A1"].LoadFromTextAsync(file2, format); @@ -169,6 +169,10 @@ private static async Task LoadFile2Async(ExcelPackage package) tbl.Columns[5].Name = "Profit"; tbl.TableStyle = TableStyles.Medium10; + //To the header row and totals font to italic, use the HeaderRowStyle and the TotalsRowStyle property. You can also use the tbl.DataStyle to style the data part of the table. + tbl.HeaderRowStyle.Font.Italic = true; + tbl.TotalsRowStyle.Font.Italic = true; + sheet.Cells[sheet.Dimension.Address].AutoFitColumns(); //Add a chart with two charttypes (Column and Line) and a secondary axis... diff --git a/06-FormulaCalculation/CalculateExistingWorkbook.cs b/06-FormulaCalculation/CalculateExistingWorkbook.cs index 3629410..0e0e853 100644 --- a/06-FormulaCalculation/CalculateExistingWorkbook.cs +++ b/06-FormulaCalculation/CalculateExistingWorkbook.cs @@ -52,7 +52,7 @@ private static void RemoveCalculatedFormulaValues(ExcelWorkbook workbook) public void Run() { //var resourceStream = GetResource("EPPlusSampleApp.Core.FormulaCalculation.FormulaCalcSample.xlsx"); - var filePath = FileInputUtil.GetFileInfo("06-FormulaCalculation", "FormulaCalcSample.xlsx").FullName; + var filePath = FileUtil.GetFileInfo("06-FormulaCalculation", "FormulaCalcSample.xlsx").FullName; using (var package = new ExcelPackage(new FileInfo(filePath))) { // Read the value from the workbook. This is calculated by Excel. diff --git a/07-OpenWorkbookAddDataAndChart/OpenWorkbookAndAddDataAndChart.cs b/07-OpenWorkbookAddDataAndChart/OpenWorkbookAndAddDataAndChart.cs index ee6af09..8d47887 100644 --- a/07-OpenWorkbookAddDataAndChart/OpenWorkbookAndAddDataAndChart.cs +++ b/07-OpenWorkbookAddDataAndChart/OpenWorkbookAndAddDataAndChart.cs @@ -29,8 +29,8 @@ public class OpenWorkbookAndAddDataAndChartSample /// public static string Run() { - FileInfo newFile = FileOutputUtil.GetFileInfo("07-OpenWorkbookAndAddDataAndChartSample.xlsx"); - FileInfo templateFile = FileInputUtil.GetFileInfo("07-OpenWorkbookAddDataAndChart", "ExistingWorkbook.xlsx"); + FileInfo newFile = FileUtil.GetCleanFileInfo("07-OpenWorkbookAndAddDataAndChartSample.xlsx"); + FileInfo templateFile = FileUtil.GetFileInfo("07-OpenWorkbookAddDataAndChart", "ExistingWorkbook.xlsx"); using (ExcelPackage package = new ExcelPackage(newFile, templateFile)) { diff --git a/08-SalesReport/SalesReport.cs b/08-SalesReport/SalesReport.cs index 1b8852b..f6d1dff 100644 --- a/08-SalesReport/SalesReport.cs +++ b/08-SalesReport/SalesReport.cs @@ -29,7 +29,7 @@ class SalesReportFromDatabase /// The connection string to the SQLite database public static string Run(string connectionString) { - var file = FileOutputUtil.GetFileInfo("08-Salesreport.xlsx"); + var file = FileUtil.GetCleanFileInfo("08-Salesreport.xlsx"); using (ExcelPackage xlPackage = new ExcelPackage(file)) { ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets.Add("Sales"); @@ -72,7 +72,7 @@ public static string Run(string connectionString) worksheet.Cells["A4:G4"].Style.Font.Bold = true; - // lets connect to the sample database for some data + //Lets connect to the sample database for some data using (var sqlConn = new SQLiteConnection(connectionString)) { sqlConn.Open(); @@ -112,13 +112,10 @@ public static string Run(string connectionString) worksheet.Cells[startRow, 6, row - 1, 6].Style.Numberformat.Format = "[$$-409]#,##0"; //Set column width - worksheet.Column(1).Width = 35; - worksheet.Column(2).Width = 28; - worksheet.Column(3).Width = 28; - worksheet.Column(4).Width = 10; - worksheet.Column(5).Width = 12; - worksheet.Column(6).Width = 12; - worksheet.Column(7).Width = 12; + worksheet.Columns[1].Width = 35; + worksheet.Columns[2, 3].Width = 28; + worksheet.Columns[4].Width = 10; + worksheet.Columns[5, 7].Width = 12; } } sqlConn.Close(); @@ -133,9 +130,10 @@ public static string Run(string connectionString) // add the file path to the footer worksheet.HeaderFooter.OddFooter.LeftAlignedText = ExcelHeaderFooter.FilePath + ExcelHeaderFooter.FileName; } - // we had better add some document properties to the spreadsheet - // set some core property values + // We can also add some document properties to the spreadsheet + + // Set some core property values xlPackage.Workbook.Properties.Title = "Sales Report"; xlPackage.Workbook.Properties.Author = "Jan Källman"; xlPackage.Workbook.Properties.Subject = "Sales Report Samples"; @@ -143,11 +141,11 @@ public static string Run(string connectionString) xlPackage.Workbook.Properties.Category = "Sales Report Samples"; xlPackage.Workbook.Properties.Comments = "This sample demonstrates how to create an Excel file from scratch using EPPlus"; - // set some extended property values + // Set some extended property values xlPackage.Workbook.Properties.Company = "Fiction Inc."; xlPackage.Workbook.Properties.HyperlinkBase = new Uri("https://EPPlusSoftware.com"); - // set some custom property values + // Set some custom property values xlPackage.Workbook.Properties.SetCustomPropertyValue("Checked by", "Jan Källman"); xlPackage.Workbook.Properties.SetCustomPropertyValue("EmployeeID", "1"); xlPackage.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "EPPlus"); diff --git a/09-PerformanceAndProtection/PerformanceAndProtectionSample.cs b/09-PerformanceAndProtection/PerformanceAndProtectionSample.cs index ccadbe4..841ca5b 100644 --- a/09-PerformanceAndProtection/PerformanceAndProtectionSample.cs +++ b/09-PerformanceAndProtection/PerformanceAndProtectionSample.cs @@ -29,7 +29,7 @@ class PerformanceAndProtectionSample /// public static string Run(int rows) { - var newFile = FileOutputUtil.GetFileInfo("09-PerformanceAndProtection.xlsx"); + var newFile = FileUtil.GetCleanFileInfo("09-PerformanceAndProtection.xlsx"); using (ExcelPackage package = new ExcelPackage()) { Console.WriteLine("{0:HH.mm.ss}\tStarting...", DateTime.Now); @@ -94,7 +94,7 @@ public static string Run(int rows) Console.WriteLine("{0:HH.mm.ss}\tAutofit columns and lock and format cells...", DateTime.Now); ws.Cells[rows - 100, 1, rows, 5].AutoFitColumns(5); //Auto fit using the last 100 rows with minimum width 5 - ws.Column(5).Width = 15; //We need to set the width for column F manually since the end sum formula is the widest cell in the column (EPPlus don't calculate any forumlas, so no output text is avalible). + ws.Columns[5].Width = 15; //We need to set the width for column F manually since the end sum formula is the widest cell in the column (EPPlus don't calculate any forumlas, so no output text is avalible). //Now we set the sheet protection and a password. ws.Cells[2, 3, rows + 1, 4].Style.Locked = false; diff --git a/10-ReadDataUsingLinq/ReadDataUsingLinq.cs b/10-ReadDataUsingLinq/ReadDataUsingLinq.cs index f4987fe..fec6f67 100644 --- a/10-ReadDataUsingLinq/ReadDataUsingLinq.cs +++ b/10-ReadDataUsingLinq/ReadDataUsingLinq.cs @@ -32,7 +32,7 @@ public static void Run() Console.WriteLine("Now open sample 9 again and perform some Linq queries..."); Console.WriteLine(); - FileInfo existingFile = FileOutputUtil.GetFileInfo("09-PerformanceAndProtection.xlsx", false); + FileInfo existingFile = FileUtil.GetFileInfo("09-PerformanceAndProtection.xlsx"); using (ExcelPackage package = new ExcelPackage(existingFile)) { ExcelWorksheet sheet = package.Workbook.Worksheets[0]; diff --git a/11-ConditionalFormatting/ConditionalFormattingSample.cs b/11-ConditionalFormatting/ConditionalFormattingSample.cs index 0a5583a..02ea9f4 100644 --- a/11-ConditionalFormatting/ConditionalFormattingSample.cs +++ b/11-ConditionalFormatting/ConditionalFormattingSample.cs @@ -33,7 +33,7 @@ class ConditionalFormatting /// public static string Run() { - FileInfo newFile = FileOutputUtil.GetFileInfo("11-ConditionalFormatting.xlsx"); + FileInfo newFile = FileUtil.GetCleanFileInfo("11-ConditionalFormatting.xlsx"); using (ExcelPackage package = new ExcelPackage(newFile)) { // add a new worksheet to the empty workbook diff --git a/12-DataValidation/DataValidationSample.cs b/12-DataValidation/DataValidationSample.cs index 535308b..e3279ff 100644 --- a/12-DataValidation/DataValidationSample.cs +++ b/12-DataValidation/DataValidationSample.cs @@ -26,7 +26,7 @@ class DataValidationSample { public static string Run() { - FileInfo output = FileOutputUtil.GetFileInfo("12-DataValidation.xlsx"); + FileInfo output = FileUtil.GetCleanFileInfo("12-DataValidation.xlsx"); using (var package = new ExcelPackage(output)) { AddIntegerValidation(package); diff --git a/13-Filter/FilterSample.cs b/13-Filter/FilterSample.cs index 092ced6..3f472cd 100644 --- a/13-Filter/FilterSample.cs +++ b/13-Filter/FilterSample.cs @@ -42,7 +42,7 @@ public static async Task RunAsync(string connectionString) //Filter on a pivot table, also see sample 24-Slicers. await PivotTableFilter(connectionString, p); - p.SaveAs(FileOutputUtil.GetFileInfo("13-Filters.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("13-Filters.xlsx")); } private static async Task ValueFilter(string connectionString, ExcelPackage p) diff --git a/13-Filter/Readme.md b/13-Filter/Readme.md index e80ffa7..5bc697f 100644 --- a/13-Filter/Readme.md +++ b/13-Filter/Readme.md @@ -2,7 +2,7 @@ These samples demonstrates the filter capabilities of EPPlus. ### [FilterSample.cs](FilterSample.cs) -The code in the RunAsync function will produce a workbook named 18-Filters.xlsx. The following filters are included: +The code in the RunAsync function will produce a workbook named 13-Filters.xlsx. The following filters are included: - Value - DateTime @@ -11,5 +11,8 @@ The code in the RunAsync function will produce a workbook named 18-Filters.xlsx. - Dynamic Above Average - Dynamic Date +### The code also demonstrates filters on tables and pivot tables +- TableFilter sample +- PivotTableFilter sample --- [Back to overview](/Readme.md) \ No newline at end of file diff --git a/14-ShapesAndImages/ShapesAndImagesSample.cs b/14-ShapesAndImages/ShapesAndImagesSample.cs index 8356ba3..365fa17 100644 --- a/14-ShapesAndImages/ShapesAndImagesSample.cs +++ b/14-ShapesAndImages/ShapesAndImagesSample.cs @@ -27,7 +27,7 @@ public static class ShapesAndImagesSample public static void Run() { //The output package - var outputFile = FileOutputUtil.GetFileInfo("14-ShapesAndImages.xlsx"); + var outputFile = FileUtil.GetCleanFileInfo("14-ShapesAndImages.xlsx"); //Create the template... using (ExcelPackage package = new ExcelPackage(outputFile)) @@ -44,25 +44,25 @@ private static void PictureSample(ExcelPackage package) var ws = package.Workbook.Worksheets.Add("Picture"); //Add an jpg image and apply some effects. - var pic = ws.Drawings.AddPicture("Landscape", FileInputUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); + var pic = ws.Drawings.AddPicture("Landscape", FileUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); pic.SetPosition(2, 0, 1, 0); pic.Effect.SetPresetShadow(ePresetExcelShadowType.OuterBottomRight); pic.Effect.OuterShadow.Distance = 10; pic.Effect.SetPresetSoftEdges(ePresetExcelSoftEdgesType.SoftEdge5Pt); //Add the same image, but with 25 percent of the size. Let the position be absolute. - pic = ws.Drawings.AddPicture("LandscapeSmall", FileInputUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); + pic = ws.Drawings.AddPicture("LandscapeSmall", FileUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); pic.SetPosition(2, 0, 16, 0); pic.SetSize(25); //25% pic.ChangeCellAnchor(eEditAs.Absolute); //Add the same image again, but let the picture move and resize when rows and colums are resized. - pic = ws.Drawings.AddPicture("LandscapeMoveAndResize", FileInputUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); + pic = ws.Drawings.AddPicture("LandscapeMoveAndResize", FileUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); pic.SetPosition(30, 0, 16, 0); pic.ChangeCellAnchor(eEditAs.TwoCell); //Add the image overlapping the first image, but make sure it is behind - pic = ws.Drawings.AddPicture("LandscapeSendToBack", FileInputUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); + pic = ws.Drawings.AddPicture("LandscapeSendToBack", FileUtil.GetFileInfo("14-ShapesAndImages", "LandscapeView.jpg")); pic.SetPosition(8, 0, 8, 0); pic.SetSize(25); //25% pic.SendToBack(); @@ -112,7 +112,7 @@ private static void FillAndColorSamples(ExcelPackage package) drawing.SetSize(250, 250); drawing.Fill.Style = eFillStyle.BlipFill; - var image = new Bitmap(FileInputUtil.GetFileInfo("14-ShapesAndImages", "EPPlusLogo.jpg").FullName); + var image = new Bitmap(FileUtil.GetFileInfo("14-ShapesAndImages", "EPPlusLogo.jpg").FullName); drawing.Fill.BlipFill.Image = image; drawing.Fill.BlipFill.Stretch = true; drawing.Text = "Blip Fill"; diff --git a/15-ChartsAndThemes/ChartTemplateSample.cs b/15-ChartsAndThemes/ChartTemplateSample.cs index 227601d..8e6da26 100644 --- a/15-ChartsAndThemes/ChartTemplateSample.cs +++ b/15-ChartsAndThemes/ChartTemplateSample.cs @@ -13,7 +13,7 @@ public static async Task AddAreaChart(string connectionString, ExcelPackage pack //Adds an Area chart from a template file. The crtx file has it's own theme, so it does not change with the theme. //The As property provides an easy type cast for drawing objects - var areaChart = ws.Drawings.AddChartFromTemplate(FileInputUtil.GetFileInfo("15-ChartsAndThemes", "AreaChartStyle3.crtx"), "areaChart") + var areaChart = ws.Drawings.AddChartFromTemplate(FileUtil.GetFileInfo("15-ChartsAndThemes", "AreaChartStyle3.crtx"), "areaChart") .As.Chart.AreaChart; var areaSerie = areaChart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); areaSerie.Header = "Order Value"; diff --git a/15-ChartsAndThemes/ChartsAndThemes.cs b/15-ChartsAndThemes/ChartsAndThemes.cs deleted file mode 100644 index 73b7ac9..0000000 --- a/15-ChartsAndThemes/ChartsAndThemes.cs +++ /dev/null @@ -1,393 +0,0 @@ -/************************************************************************************************* - Required Notice: Copyright (C) EPPlus Software AB. - This software is licensed under PolyForm Noncommercial License 1.0.0 - and may only be used for noncommercial purposes - https://polyformproject.org/licenses/noncommercial/1.0.0/ - - A commercial license to use this software can be purchased at https://epplussoftware.com - ************************************************************************************************* - Date Author Change - ************************************************************************************************* - 01/27/2020 EPPlus Software AB Initial release EPPlus 5 - *************************************************************************************************/ -using OfficeOpenXml; -using System.Drawing; -using OfficeOpenXml.Style; -using System.Data.SQLite; -using System.Threading.Tasks; -using OfficeOpenXml.Drawing.Chart; -using OfficeOpenXml.Drawing.Chart.Style; -using System; -using OfficeOpenXml.Drawing; -using System.Collections.Generic; -using OfficeOpenXml.Table; -using System.Data; -using System.IO; - -namespace EPPlusSamples -{ - class ChartsAndThemesSample - { - private class RegionData - { - public string Region { get; set; } - public int SoldUnits { get; set; } - public double TotalSales { get; set; } - public double Margin { get; set; } - } - /// - /// Sample 15 - Creates various charts and apply a theme if supplied in the parameter themeFile. - /// - public static async Task RunAsync(string connectionString, FileInfo xlFile, FileInfo themeFile) - { - using (var package = new ExcelPackage()) - { - //Load a theme file if set. Thmx files can be exported from Excel. This will change the appearance for the workbook. - if (themeFile != null) - { - package.Workbook.ThemeManager.Load(themeFile); - /*** Themes can also be altered. For example, uncomment this code to set the Accent1 to a blue color ***/ - //package.Workbook.ThemeManager.CurrentTheme.ColorScheme.Accent1.SetRgbColor(Color.FromArgb(32, 78, 224)); - } - - /********************************************************************************************************* - * About chart styles: - * - * Chart styles can be applied to charts using the Chart.StyleManager.SetChartMethod method. - * The chart styles can either be set by the two enums ePresetChartStyle and ePresetChartStyleMultiSeries or by setting the Chart Style Number. - * - * Note: Chart styles in Excel changes depending on many parameters (like number of series, axis types and more), so the enums will not always reflect the style index in Excel. - * The enums are for the most common scenarios. - * If you want to reflect a specific style please use the Chart Style Number for the chart in Excel. - * The chart style number can be fetched by recording a macro in Excel and click the style you want to apply. - * - * Chart style do not alter visibility of chart objects like datalabels or chart titles like Excel do. That must be set in code before setting the style. - *********************************************************************************************************/ - - //The first method adds a worksheet with four 3D charts with different styles. The last chart applies an exported chart template file (*.crtx) to the chart. - await Add3DCharts(connectionString, package); - - //This method adds four line charts with different chart elements like up-down bars, error bars, drop lines and high-low lines. - await AddLineCharts(connectionString, package); - - //Adds a scatter chart with a moving average trendline. - AddScatterChart(package); - - //Adds a bubble-chartsheet - AddBubbleChartsWorksheet(package); - - //Adds a radar chart - AddRadarChart(package); - - //Add an area chart using a chart template (chrx file) - await AddAreaFromChartTemplate(connectionString, package); ; - - //Save our new workbook in the output directory and we are done! - package.SaveAs(xlFile); - return xlFile.FullName; - } - } - - private static async Task AddAreaFromChartTemplate(string connectionString, ExcelPackage package) - { - var ws = package.Workbook.Worksheets.Add("Area chart from template"); - var range = await LoadFromDatabase(connectionString, ws); - - //Add an Area chart from a template file. The crtx file has it's own theme, so it does not change if you apply another theme. - var template = FileInputUtil.GetFileInfo("15-ChartsAndThemes", "AreaChartStyle3.crtx"); - var areaChart = (ExcelAreaChart)ws.Drawings.AddChartFromTemplate(template, "areaChart"); - var areaSerie = areaChart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - areaSerie.Header = "Order Value"; - areaChart.SetPosition(1, 0, 6, 0); - areaChart.SetSize(1200, 400); - areaChart.Title.Text = "Area Chart"; - - range.AutoFitColumns(0); - } - private static void AddScatterChart(ExcelPackage package) - { - //Add a scatter chart on the data with one serie per row. - var ws = package.Workbook.Worksheets.Add("Scatter Chart"); - - CreateIceCreamData(ws); - - var chart = ws.Drawings.AddScatterChart("ScatterChart1", eScatterChartType.XYScatter); - chart.SetPosition(1, 0, 3, 0); - chart.To.Column = 18; - chart.To.Row = 20; - chart.XAxis.Format = "yyyy-mm"; - chart.XAxis.Title.Text = "Period"; - chart.XAxis.MajorGridlines.Width = 1; - chart.YAxis.Format = "$#,##0"; - chart.YAxis.Title.Text = "Sales"; - - chart.Legend.Position = eLegendPosition.Bottom; - - var serie = chart.Series.Add(ws.Cells[3, 2, 14, 2], ws.Cells[3, 1, 14, 1]); - serie.HeaderAddress = ws.Cells["A1"]; - var tr=serie.TrendLines.Add(eTrendLine.MovingAvgerage); - tr.Name = "Icecream Sales-Monthly Average"; - chart.StyleManager.SetChartStyle(ePresetChartStyle.ScatterChartStyle12); - } - - private static void AddBubbleChartsWorksheet(ExcelPackage package) - { - ExcelWorksheet wsData = LoadBubbleChartData(package); - - //Add a bubble chart on the data with one serie per row. - var wsChart = package.Workbook.Worksheets.AddChart("Bubble Chart", eChartType.Bubble); - var chart = ((ExcelBubbleChart)wsChart.Chart); - for (int row = 2; row <= 7; row++) - { - var serie = chart.Series.Add(wsData.Cells[row, 2], wsData.Cells[row, 3], wsData.Cells[row, 4]); - serie.HeaderAddress = wsData.Cells[row, 1]; - } - - chart.DataLabel.Position = eLabelPosition.Center; - chart.DataLabel.ShowSeriesName = true; - chart.DataLabel.ShowBubbleSize = true; - chart.Title.Text = "Sales per Region"; - chart.XAxis.Title.Text = "Total Sales"; - chart.XAxis.Title.Font.Size = 12; - chart.XAxis.MajorGridlines.Width = 1; - chart.YAxis.Title.Text = "Sold Units"; - chart.YAxis.Title.Font.Size = 12; - chart.Legend.Position = eLegendPosition.Bottom; - - chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.BubbleChartStyle10); - } - - private static async Task Add3DCharts(string connectionString, ExcelPackage package) - { - var ws = package.Workbook.Worksheets.Add("3D Charts"); - - var range = await LoadFromDatabase(connectionString, ws); - - //Add a column chart - var chart = ws.Drawings.AddBarChart("column3dChart", eBarChartType.ColumnClustered3D); - var serie = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 26, 1]); - serie.Header = "Order Value"; - chart.SetPosition(0, 0, 6, 0); - chart.SetSize(1200, 400); - chart.Title.Text = "Column Chart 3D"; - - //Set style 9 and Colorful Palette 3. - chart.StyleManager.SetChartStyle(ePresetChartStyle.Column3dChartStyle9, ePresetChartColors.ColorfulPalette3); - - //Add a line chart - var lineChart = ws.Drawings.AddLineChart("line3dChart", eLineChartType.Line3D); - var lineSerie = lineChart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - lineSerie.Header = "Order Value"; - lineChart.SetPosition(21, 0, 6, 0); - lineChart.SetSize(1200, 400); - lineChart.Title.Text = "Line 3D"; - //Set Line3D Style 1 - lineChart.StyleManager.SetChartStyle(ePresetChartStyle.Line3dChartStyle1); - - //Add a bar chart - chart = ws.Drawings.AddBarChart("bar3dChart", eBarChartType.BarStacked3D); - serie = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - serie.Header = "Order Value"; - serie = chart.Series.Add(ws.Cells[2, 3, 16, 3], ws.Cells[2, 1, 16, 1]); - serie.Header = "Tax"; - serie = chart.Series.Add(ws.Cells[2, 4, 16, 4], ws.Cells[2, 1, 16, 1]); - serie.Header = "Freight"; - - chart.SetPosition(42, 0, 6, 0); - chart.SetSize(1200, 600); - chart.Title.Text = "Bar Chart 3D"; - //Set the color - chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.StackedBar3dChartStyle7, ePresetChartColors.ColorfulPalette1); - - range.AutoFitColumns(0); - } - private static async Task AddLineCharts(string connectionString, ExcelPackage package) - { - var ws = package.Workbook.Worksheets.Add("LineCharts"); - - var range = await LoadFromDatabase(connectionString, ws); - - //Add a line chart - var chart = ws.Drawings.AddLineChart("LineChartWithDroplines", eLineChartType.Line); - var serie = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - serie.Header = "Order Value"; - chart.SetPosition(0, 0, 6, 0); - chart.SetSize(1200, 400); - chart.Title.Text = "Line Chart With Droplines"; - chart.AddDropLines(); - chart.DropLine.Border.Width = 2; - //Set style 12 - chart.StyleManager.SetChartStyle(ePresetChartStyle.LineChartStyle12); - - //Add a line chart with Error Bars - chart = ws.Drawings.AddLineChart("LineChartWithErrorBars", eLineChartType.Line); - serie = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - serie.Header = "Order Value"; - chart.SetPosition(21, 0, 6, 0); - chart.SetSize(1200, 400); //Make this chart wider to make room for the datatable. - chart.Title.Text = "Line Chart With Error Bars"; - serie.AddErrorBars(eErrorBarType.Both, eErrorValueType.Percentage); - serie.ErrorBars.Value = 5; - chart.PlotArea.CreateDataTable(); - - //Set style 2 - chart.StyleManager.SetChartStyle(ePresetChartStyle.LineChartStyle2); - - //Add a line chart with Error Bars - chart = ws.Drawings.AddLineChart("LineChartWithUpDownBars", eLineChartType.Line); - var serie1 = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); - serie1.Header = "Order Value"; - var serie2 = chart.Series.Add(ws.Cells[2, 3, 16, 3], ws.Cells[2, 1, 16, 1]); - serie2.Header = "Tax"; - var serie3 = chart.Series.Add(ws.Cells[2, 4, 16, 4], ws.Cells[2, 1, 16, 1]); - serie3.Header = "Freight"; - chart.SetPosition(42, 0, 6, 0); - chart.SetSize(1200, 400); - chart.Title.Text = "Line Chart With Up/Down Bars"; - chart.AddUpDownBars(true, true); - - //Set style 10, Note: As this is a line chart with multiple series, we use the enum for multiple series. Charts with multiple series usually has a subset of of the chart styles in Excel. - //Another option to set the style is to use the Excel Style number, in this case 236: chart.StyleManager.SetChartStyle(236) - chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.LineChartStyle9); - range.AutoFitColumns(0); - - - //Add a line chart with high/low Bars - chart = ws.Drawings.AddLineChart("LineChartWithHighLowLines", eLineChartType.Line); - serie1 = chart.Series.Add(ws.Cells[2, 2, 26, 2], ws.Cells[2, 1, 26, 1]); - serie1.Header = "Order Value"; - serie2 = chart.Series.Add(ws.Cells[2, 3, 26, 3], ws.Cells[2, 1, 26, 1]); - serie2.Header = "Tax"; - serie3 = chart.Series.Add(ws.Cells[2, 4, 26, 4], ws.Cells[2, 1, 26, 1]); - serie3.Header = "Freight"; - chart.SetPosition(63, 0, 6, 0); - chart.SetSize(1200, 400); - chart.Title.Text = "Line Chart With High/Low Lines"; - chart.AddHighLowLines(); - - //Set the style using the Excel ChartStyle number. The chart style must exist in the ExcelChartStyleManager.StyleLibrary[]. - //Styles can be added and removed from this library. By default it is loaded with the styles for EPPlus supported chart types. - chart.StyleManager.SetChartStyle(237); - range.AutoFitColumns(0); - } - private static void AddRadarChart(ExcelPackage package) - { - var ws = package.Workbook.Worksheets.Add("RadarChart"); - - var dt=GetCarDataTable(); - ws.Cells["A1"].LoadFromDataTable(dt, true); - ws.Cells.AutoFitColumns(); - - var chart = ws.Drawings.AddRadarChart("RadarChart1", eRadarChartType.RadarFilled); - var serie = chart.Series.Add(ws.Cells["B2:B5"], ws.Cells["A2:A5"]); - serie.HeaderAddress = ws.Cells["B1"]; - serie = chart.Series.Add(ws.Cells["C2:C5"], ws.Cells["A2:A5"]); - serie.HeaderAddress = ws.Cells["C1"]; - serie = chart.Series.Add(ws.Cells["D2:D5"], ws.Cells["A2:A5"]); - serie.HeaderAddress = ws.Cells["D1"]; - serie = chart.Series.Add(ws.Cells["E2:E5"], ws.Cells["A2:A5"]); - serie.HeaderAddress = ws.Cells["E1"]; - - chart.Legend.Position = eLegendPosition.Top; - chart.StyleManager.SetChartStyle(ePresetChartStyleMultiSeries.RadarChartStyle4); - - //If you want to apply custom styling do that after setting the chart style so its not overwritten. - chart.Legend.Effect.SetPresetShadow(ePresetExcelShadowType.OuterTopLeft); - - chart.SetPosition(0, 0, 6, 0); - chart.To.Column = 17; - chart.To.Row = 30; - } - - private static DataTable GetCarDataTable() - { - var dt = new DataTable(); - dt.Columns.Add("Car", typeof(string)); - dt.Columns.Add("Acceleration Index", typeof(int)); - dt.Columns.Add("Size Index", typeof(int)); - dt.Columns.Add("Polution Index", typeof(int)); - dt.Columns.Add("Retro Index", typeof(int)); - dt.Rows.Add("Volvo 242", 1, 3, 4, 4); - dt.Rows.Add("Lamborghini Countach", 5, 1, 5, 4); - dt.Rows.Add("Tesla Model S", 5, 2, 1, 1); - dt.Rows.Add("Hummer H1", 2, 5, 5, 2); - - return dt; - } - - private static async Task LoadFromDatabase(string connectionString, ExcelWorksheet ws) - { - ExcelRangeBase range; - using (var sqlConn = new SQLiteConnection(connectionString)) - { - sqlConn.Open(); - using (var sqlCmd = new SQLiteCommand("select orderdate as OrderDate, SUM(ordervalue) as OrderValue, SUM(tax) As Tax,SUM(freight) As Freight from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId Where Currency='USD' group by OrderDate ORDER BY OrderDate desc limit 15", sqlConn)) - { - using (var sqlReader = sqlCmd.ExecuteReader()) - { - range = await ws.Cells["A1"].LoadFromDataReaderAsync(sqlReader, true); - range.Offset(0, 0, 1, range.Columns).Style.Font.Bold = true; - range.Offset(0, 0, range.Rows, 1).Style.Numberformat.Format = "yyyy-MM-dd"; - } - //Set the numberformat - } - } - return range; - } - private static void CreateIceCreamData(ExcelWorksheet ws) - { - ws.SetValue("A1", "Icecream Sales-2019"); - ws.SetValue("A2", "Date"); - ws.SetValue("B2", "Sales"); - ws.SetValue("A3", new DateTime(2019, 1, 1)); - ws.SetValue("B3", 2500); - ws.SetValue("A4", new DateTime(2019, 2, 1)); - ws.SetValue("B4", 3000); - ws.SetValue("A5", new DateTime(2019, 3, 1)); - ws.SetValue("B5", 2700); - ws.SetValue("A6", new DateTime(2019, 4, 1)); - ws.SetValue("B6", 4400); - ws.SetValue("A7", new DateTime(2019, 5, 1)); - ws.SetValue("B7", 6900); - ws.SetValue("A8", new DateTime(2019, 6, 1)); - ws.SetValue("B8", 11200); - ws.SetValue("A9", new DateTime(2019, 7, 1)); - ws.SetValue("B9", 13200); - ws.SetValue("A10", new DateTime(2019, 8, 1)); - ws.SetValue("B10", 12400); - ws.SetValue("A11", new DateTime(2019, 9, 1)); - ws.SetValue("B11", 8700); - ws.SetValue("A12", new DateTime(2019, 10, 1)); - ws.SetValue("B12", 4800); - ws.SetValue("A13", new DateTime(2019, 11, 1)); - ws.SetValue("B13", 2000); - ws.SetValue("A14", new DateTime(2019, 12, 1)); - ws.SetValue("B14", 2400); - ws.Cells["A3:A14"].Style.Numberformat.Format = "yyyy-MM"; - ws.Cells["B3:B14"].Style.Numberformat.Format = "#,##0kr"; - } - private static ExcelWorksheet LoadBubbleChartData(ExcelPackage package) - { - var data = new List() - { - new RegionData(){ Region = "North", SoldUnits=500, TotalSales=4800, Margin=0.200 }, - new RegionData(){ Region = "Central", SoldUnits=900, TotalSales=7330, Margin=0.333 }, - new RegionData(){ Region = "South", SoldUnits=400, TotalSales=3700, Margin=0.150 }, - new RegionData(){ Region = "East", SoldUnits=350, TotalSales=4400, Margin=0.102 }, - new RegionData(){ Region = "West", SoldUnits=700, TotalSales=6900, Margin=0.218 }, - new RegionData(){ Region = "Stockholm", SoldUnits=1200, TotalSales=8250, Margin=0.350 } - }; - var wsData = package.Workbook.Worksheets.Add("ChartData"); - wsData.Cells["A1"].LoadFromCollection(data, true, TableStyles.Medium15); - wsData.Cells["B2:C7"].Style.Numberformat.Format = "#,##0"; - wsData.Cells["D2:D7"].Style.Numberformat.Format = "#,##0.00%"; - - var shape = wsData.Drawings.AddShape("Shape1", eShapeStyle.Rect); - shape.Text = "This worksheet contains the data for the bubble-chartsheet"; - shape.SetPosition(1, 0, 6, 0); - shape.Effect.SetPresetShadow(ePresetExcelShadowType.OuterBottomLeft); - return wsData; - } - - } -} diff --git a/15-ChartsAndThemes/ChartsAndThemesSample.cs b/15-ChartsAndThemes/ChartsAndThemesSample.cs index 9c586ef..36554d1 100644 --- a/15-ChartsAndThemes/ChartsAndThemesSample.cs +++ b/15-ChartsAndThemes/ChartsAndThemesSample.cs @@ -66,7 +66,10 @@ public static async Task RunAsync(string connectionString, FileInfo xlFi //Adds a scatter chart with a moving average trendline. ScatterChartSample.Add(package); - + + //Adds a column chart with a legend where we style and remove individual legend items. + await ColumnChartWithLegendSample.Add(connectionString, package); + //Adds a bubble-chartsheet ChartWorksheetSample.Add(package); @@ -79,13 +82,13 @@ public static async Task RunAsync(string connectionString, FileInfo xlFi //Adds a sunburst and a treemap chart await SunburstAndTreemapChartSample.Add(connectionString, package); - //Add a box & whisker and a histogram chart + //Adds a box & whisker and a histogram chart BoxWhiskerHistogramChartSample.Add(package); - // Add a waterfall chart + // Adds a waterfall chart WaterfallChartSample.Add(package); - // Add a funnel chart + // Adds a funnel chart FunnelChartSample.Add(package); await RegionMapChartSample.Add(connectionString, package); diff --git a/15-ChartsAndThemes/ColumnChartsWithLegendSample.cs b/15-ChartsAndThemes/ColumnChartsWithLegendSample.cs new file mode 100644 index 0000000..19552f3 --- /dev/null +++ b/15-ChartsAndThemes/ColumnChartsWithLegendSample.cs @@ -0,0 +1,40 @@ +using OfficeOpenXml; +using OfficeOpenXml.Drawing; +using OfficeOpenXml.Drawing.Chart; +using OfficeOpenXml.Drawing.Chart.Style; +using System.Drawing; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public class ColumnChartWithLegendSample : ChartSampleBase + { + public static async Task Add(string connectionString, ExcelPackage package) + { + var ws = package.Workbook.Worksheets.Add("ColumnCharts"); + + var range = await LoadFromDatabase(connectionString, ws); + + //Add a line chart + var chart = ws.Drawings.AddBarChart("ColumnChartWithLegend", eBarChartType.ColumnStacked); + var serie1 = chart.Series.Add(ws.Cells[2, 2, 16, 2], ws.Cells[2, 1, 16, 1]); + serie1.Header = "Order Value"; + var serie2 = chart.Series.Add(ws.Cells[2, 3, 16, 3], ws.Cells[2, 1, 16, 1]); + serie2.Header = "Tax"; + var serie3 = chart.Series.Add(ws.Cells[2, 4, 16, 4], ws.Cells[2, 1, 16, 1]); + serie3.Header = "Freight"; + chart.SetPosition(0, 0, 6, 0); + chart.SetSize(1200, 400); + chart.Title.Text = "Column chart"; + + //Set style 10 + chart.StyleManager.SetChartStyle(ePresetChartStyle.ColumnChartStyle10); + + chart.Legend.Entries[0].Font.Fill.Color = Color.Red; + chart.Legend.Entries[1].Font.Fill.Color = Color.Green; + chart.Legend.Entries[2].Deleted = true; + + range.AutoFitColumns(0); + } + } +} diff --git a/15-ChartsAndThemes/Readme.md b/15-ChartsAndThemes/Readme.md index b97a7b7..ec78558 100644 --- a/15-ChartsAndThemes/Readme.md +++ b/15-ChartsAndThemes/Readme.md @@ -1,5 +1,5 @@ # 15 - Chart Styling and Themes -Demonstrates how to use chart styling and themes +Demonstrates how to use various types of charts, chart styling and themes ### [ChartsAndThemes.cs](ChartsAndThemes.cs) diff --git a/16-Sparklines/SparklinesSample.cs b/16-Sparklines/SparklinesSample.cs index d7e60e2..bc42d64 100644 --- a/16-Sparklines/SparklinesSample.cs +++ b/16-Sparklines/SparklinesSample.cs @@ -43,7 +43,7 @@ public static void Run() // Add a new worksheet to the empty workbook and load the fx rates from the text var ws = package.Workbook.Worksheets.Add("SEKRates"); - + //Load the sample data with a Swedish culture setting ws.Cells["A1"].LoadFromText(txt, new ExcelTextFormat() { Delimiter = ';', Culture = CultureInfo.GetCultureInfo("sv-SE") }, TableStyles.Light10, true); ws.Cells["A2:A12"].Style.Numberformat.Format = "yyyy-mm-dd"; @@ -52,7 +52,7 @@ public static void Run() ws.Cells["A15"].Value = "Column"; var sparklineCol = ws.SparklineGroups.Add(eSparklineType.Column, ws.Cells["B15:Q15"], ws.Cells["B2:Q12"]); sparklineCol.High = true; - sparklineCol.ColorHigh.SetColor(Color.Red); + sparklineCol.ColorHigh.SetColor(Color.Red); // Add a line sparkline for all currencies ws.Cells["A16"].Value = "Line"; @@ -72,11 +72,9 @@ public static void Run() ws.Cells["A15:A17"].Style.Font.Bold = true; ws.Cells.AutoFitColumns(); - ws.Row(15).Height = 40; - ws.Row(16).Height = 40; - ws.Row(17).Height = 40; + ws.Rows[15, 17].Height = 40; - package.SaveAs(FileOutputUtil.GetFileInfo("16-Sparklines.xlsx")); + package.SaveAs(FileUtil.GetCleanFileInfo("16-Sparklines.xlsx")); } } } diff --git a/17-FXReportFromDatabase/FXReportFromDatabase.cs b/17-FXReportFromDatabase/FXReportFromDatabase.cs index 720a594..cb9846a 100644 --- a/17-FXReportFromDatabase/FXReportFromDatabase.cs +++ b/17-FXReportFromDatabase/FXReportFromDatabase.cs @@ -38,7 +38,7 @@ class FxReportFromDatabase /// public static string Run(string connectionString) { - FileInfo template = FileInputUtil.GetFileInfo("17-FXReportFromDatabase", "GraphTemplate.xlsx"); + FileInfo template = FileUtil.GetFileInfo("17-FXReportFromDatabase", "GraphTemplate.xlsx"); using (ExcelPackage p = new ExcelPackage(template, true)) { @@ -132,14 +132,18 @@ public static string Run(string connectionString) chart.Legend.Position = eLegendPosition.Bottom; + //Set Font bold on USD/EUR in the legend. + chart.Legend.Entries[1].Font.Bold = true; + //Set the chart style chart.StyleManager.SetChartStyle(236); + } - + //Get the documet as a byte array from the stream and save it to disk. (This is useful in a webapplication) ... var bin = p.GetAsByteArray(); - FileInfo file = FileOutputUtil.GetFileInfo("17-FxReportFromDatabase.xlsx"); + FileInfo file = FileUtil.GetCleanFileInfo("17-FxReportFromDatabase.xlsx"); File.WriteAllBytes(file.FullName, bin); return file.FullName; } diff --git a/18-PivotTables/PivotTablesSample.cs b/18-PivotTables/PivotTablesSample.cs index 5bb9d96..f267c5c 100644 --- a/18-PivotTables/PivotTablesSample.cs +++ b/18-PivotTables/PivotTablesSample.cs @@ -46,7 +46,7 @@ public static string Run(string connectionStr) { var list = GetDataFromSQL(connectionStr); - FileInfo newFile = FileOutputUtil.GetFileInfo("18-PivotTables.xlsx"); + FileInfo newFile = FileUtil.GetCleanFileInfo("18-PivotTables.xlsx"); using (ExcelPackage pck = new ExcelPackage(newFile)) { // get the handle to the existing worksheet @@ -311,17 +311,17 @@ private static ExcelPivotTable CreatePivotTableWithDataFieldsUsingShowAs(ExcelPa df2.Name = "Order value % of total"; df2.ShowDataAs.SetPercentOfColumn(); df2.Format = "0.0%;"; - + var df3 = pivotTable5.DataFields.Add(pivotTable5.Fields["OrderValue"]); df3.Name = "Count Difference From Previous"; df3.ShowDataAs.SetDifference(rowField1, ePrevNextPivotItem.Previous); df3.Function = DataFieldFunctions.Count; df3.Format = "#,##0"; - + pivotTable5.SetCompact(false); pivotTable5.ColumnHeaderCaption = "Data"; - pivotTable5.ShowColumnStripes = true; - wsPivot5.Column(1).Width = 30; + pivotTable5.ShowColumnStripes = true; + wsPivot5.Columns[1].Width = 30; return pivotTable5; } diff --git a/18-PivotTables/PivotTablesStylingSample.cs b/18-PivotTables/PivotTablesStylingSample.cs index 8518bd7..e055928 100644 --- a/18-PivotTables/PivotTablesStylingSample.cs +++ b/18-PivotTables/PivotTablesStylingSample.cs @@ -35,8 +35,8 @@ public static class PivotTablesStylingSample { public static string Run() { - FileInfo templateFile = FileOutputUtil.GetFileInfo("18-PivotTables.xlsx", false); - FileInfo newFile = FileOutputUtil.GetFileInfo("18-PivotTables-Styling.xlsx"); + FileInfo templateFile = FileUtil.GetFileInfo("18-PivotTables.xlsx"); + FileInfo newFile = FileUtil.GetFileInfo("18-PivotTables-Styling.xlsx"); using ( ExcelPackage pck = new ExcelPackage(newFile, templateFile)) { //These two sample shows how to style different parts on the pivot table using pivot areas. diff --git a/19-EncryptionAndProtection/EncryptionAndProtectionSample.cs b/19-EncryptionAndProtection/EncryptionAndProtectionSample.cs index 96fc316..b5c0f30 100644 --- a/19-EncryptionAndProtection/EncryptionAndProtectionSample.cs +++ b/19-EncryptionAndProtection/EncryptionAndProtectionSample.cs @@ -26,12 +26,12 @@ public static class DrawingsSample public static void Run() { //Create a Sample 19 directory... - var outputDir = FileOutputUtil.GetDirectoryInfo("19-EncryptionAndProtection"); + var outputDir = FileUtil.GetDirectoryInfo("19-EncryptionAndProtection"); //create the three FileInfo objects... - FileInfo templateFile = FileOutputUtil.GetFileInfo(outputDir, "template.xlsx"); - FileInfo answerFile = FileOutputUtil.GetFileInfo(outputDir, "answers.xlsx"); - FileInfo JKAnswerFile = FileOutputUtil.GetFileInfo(outputDir, "JKAnswers.xlsx"); + FileInfo templateFile = FileUtil.GetFileInfo(outputDir, "template.xlsx"); + FileInfo answerFile = FileUtil.GetFileInfo(outputDir, "answers.xlsx"); + FileInfo JKAnswerFile = FileUtil.GetFileInfo(outputDir, "JKAnswers.xlsx"); //Create the template... using (ExcelPackage package = new ExcelPackage(templateFile)) @@ -66,9 +66,9 @@ public static void Run() sheet.Cells["A1"].Style.Font.Size = 18; sheet.Cells["A3"].Value = "Enter your name:"; - sheet.Column(1).Width = 30; - sheet.Column(2).Width = 80; - sheet.Column(3).Width = 20; + sheet.Columns[1].Width = 30; + sheet.Columns[2].Width = 80; + sheet.Columns[3].Width = 20; sheet.Cells["A7"].Value = "What is the name of the capital of Sweden?"; sheet.Cells["A9"].Value = "At which place did the Swedish team end up in the Soccer Worldcup 1994?"; diff --git a/20-CreateFileSystemReport/CreateAFileSystemReport.cs b/20-CreateFileSystemReport/CreateAFileSystemReport.cs index f88feeb..bd59640 100644 --- a/20-CreateFileSystemReport/CreateAFileSystemReport.cs +++ b/20-CreateFileSystemReport/CreateAFileSystemReport.cs @@ -64,7 +64,7 @@ public static string Run(DirectoryInfo dir, int depth, bool skipIcons) { _maxLevels = depth; - FileInfo newFile = FileOutputUtil.GetFileInfo("20-CreateAFileSystemReport.xlsx"); + FileInfo newFile = FileUtil.GetCleanFileInfo("20-CreateAFileSystemReport.xlsx"); //Create the workbook ExcelPackage pck = new ExcelPackage(newFile); @@ -73,17 +73,14 @@ public static string Run(DirectoryInfo dir, int depth, bool skipIcons) ws.View.ShowGridLines = false; - ws.Column(1).Width = 2.5; - ws.Column(2).Width = 60; - ws.Column(3).Width = 16; - ws.Column(4).Width = 20; - ws.Column(5).Width = 20; + ws.Columns[1].Width = 2.5; + ws.Columns[2].Width = 60; + ws.Columns[3].Width = 16; + ws.Columns[4, 5].Width = 20; //This set the outline for column 4 and 5 and hide them - ws.Column(4).OutlineLevel = 1; - ws.Column(4).Collapsed = true; - ws.Column(5).OutlineLevel = 1; - ws.Column(5).Collapsed = true; + ws.Columns[4, 5].OutlineLevel = 1; + ws.Columns[4, 5].Collapsed = true; ws.OutLineSummaryRight = true; //Headers @@ -405,7 +402,7 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d { Bitmap icon = GetIcon(dir.FullName); - ws.Row(row).Height = height; + ws.Rows[row].Height = height; //Add the icon as a picture if (icon != null) { @@ -419,7 +416,7 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d ws.Cells[row, 2, row, 5].Style.Font.Bold = true; //Sets the outline depth - ws.Row(row).OutlineLevel = level; + ws.Rows[row].OutlineLevel = level; int prevRow = row; row++; @@ -439,7 +436,7 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d { Bitmap fileIcon = GetIcon(file.FullName); - ws.Row(row).Height = height; + ws.Rows[row].Height = height; if (fileIcon != null) { ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), fileIcon); @@ -452,7 +449,7 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d ws.Cells[row, 4].Value = file.CreationTime; ws.Cells[row, 5].Value = file.LastAccessTime; - ws.Row(row).OutlineLevel = level+1; + ws.Rows[row].OutlineLevel = level+1; AddStatistics(file); diff --git a/21-VBA/WorkingWithVbaSample.cs b/21-VBA/WorkingWithVbaSample.cs index 6d1d1ce..27dec37 100644 --- a/21-VBA/WorkingWithVbaSample.cs +++ b/21-VBA/WorkingWithVbaSample.cs @@ -53,12 +53,12 @@ private static void SimpleVba() pck.Workbook.CodeModule.Code = sb.ToString(); //And Save as xlsm - FileInfo fi = FileOutputUtil.GetFileInfo("21.1-SimpleVba.xlsm"); + FileInfo fi = FileUtil.GetCleanFileInfo("21.1-SimpleVba.xlsm"); pck.SaveAs(fi); } private static void AddABubbleChart() { - FileInfo sample1File = FileOutputUtil.GetFileInfo("01-GettingStarted.xlsx", false); + FileInfo sample1File = FileUtil.GetFileInfo("01-GettingStarted.xlsx"); //Open Sample 1 again ExcelPackage pck = new ExcelPackage(sample1File); var p = new ExcelPackage(); @@ -88,7 +88,7 @@ private static void AddABubbleChart() //pck.Workbook.VbaProject.Signature.Certificate = store.Certificates[0]; //And Save as xlsm - FileInfo fi =FileOutputUtil.GetFileInfo("21.2-AddABubbleChartVba.xlsm"); + FileInfo fi =FileUtil.GetCleanFileInfo("21.2-AddABubbleChartVba.xlsm"); pck.SaveAs(fi); } private static void CreateABattleShipsGame() @@ -123,7 +123,7 @@ private static void CreateABattleShipsGame() //Password protect your code pck.Workbook.VbaProject.Protection.SetPassword("EPPlus"); - var codeDir = FileInputUtil.GetSubDirectory("21-VBA", "VBA-Code"); + var codeDir = FileUtil.GetSubDirectory("21-VBA", "VBA-Code"); //Add all the code from the textfiles in the Vba-Code sub-folder. pck.Workbook.CodeModule.Code = GetCodeModule(codeDir, "ThisWorkbook.txt"); @@ -170,7 +170,7 @@ private static void CreateABattleShipsGame() //Set the headers. ws.SetValue("B1", "Computer Grid"); ws.SetValue("M1", "Your Grid"); - ws.Row(1).Style.Font.Size = 18; + ws.Rows[1].Style.Font.Size = 18; AddChart(ws.Cells["B13"], "chtHitPercent", "Player"); AddChart(ws.Cells["M13"], "chtComputerHitPercent", "Computer"); @@ -198,13 +198,13 @@ private static void CreateABattleShipsGame() // } //} - var fi = FileOutputUtil.GetFileInfo(@"21.3-CreateABattleShipsGameVba.xlsm"); + var fi = FileUtil.GetCleanFileInfo(@"21.3-CreateABattleShipsGameVba.xlsm"); pck.SaveAs(fi); } private static string GetCodeModule(DirectoryInfo codeDir, string fileName) { - return File.ReadAllText(FileOutputUtil.GetFileInfo(codeDir, fileName, false).FullName); + return File.ReadAllText(FileUtil.GetFileInfo(codeDir, fileName, false).FullName); } private static void AddChart(ExcelRange rng,string name, string prefix) diff --git a/22-IgnoreErrors/IgnoreErrorsSample.cs b/22-IgnoreErrors/IgnoreErrorsSample.cs index 9d02355..1a4447f 100644 --- a/22-IgnoreErrors/IgnoreErrorsSample.cs +++ b/22-IgnoreErrors/IgnoreErrorsSample.cs @@ -52,7 +52,7 @@ public static void Run() ie = ws.IgnoredErrors.Add(ws.Cells["D2,D4"]); ie.Formula = true; // Ignore the inconsistant formula error - p.SaveAs(FileOutputUtil.GetFileInfo("22-IgnoreErrors.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("22-IgnoreErrors.xlsx")); } } } diff --git a/23-Comments/CommentsSample.cs b/23-Comments/CommentsSample.cs index 2098517..65a102c 100644 --- a/23-Comments/CommentsSample.cs +++ b/23-Comments/CommentsSample.cs @@ -20,7 +20,7 @@ public static void Run() // Threaded comments var sheet2 = package.Workbook.Worksheets.Add("ThreadedComments"); AddAndReadThreadedComments(sheet2); - package.SaveAs(FileOutputUtil.GetFileInfo("23-Comments.xlsx")); + package.SaveAs(FileUtil.GetCleanFileInfo("23-Comments.xlsx")); } } @@ -134,7 +134,7 @@ private static void AddAndReadThreadedComments(ExcelWorksheet sheet) // remove the comment thread2.Remove(c); if (thread2.Comments.Count == 0) - Console.WriteLine("B1 is now empty"); + Console.WriteLine("Thread is now empty"); } } } diff --git a/24-Slicers/SlicerSample.cs b/24-Slicers/SlicerSample.cs index 3aebe32..f89fcec 100644 --- a/24-Slicers/SlicerSample.cs +++ b/24-Slicers/SlicerSample.cs @@ -1,7 +1,10 @@ using OfficeOpenXml; using OfficeOpenXml.Drawing; using OfficeOpenXml.Filter; +using System; +using System.Collections.Generic; using System.Data.SQLite; +using System.Text; namespace EPPlusSamples { @@ -22,7 +25,7 @@ public static void Run(string connectionString) //Create three slicers and two pivot tables, one that connects to both tables and two that connect to each of the tables. PivotTableOneSlicerToMultiplePivotTables(p); - p.SaveAs(FileOutputUtil.GetFileInfo("24-Slicers.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("24-Slicers.xlsx")); } } diff --git a/26-FormControls/FormControlsSample.cs b/26-FormControls/FormControlsSample.cs index d0b8cc2..89f02ba 100644 --- a/26-FormControls/FormControlsSample.cs +++ b/26-FormControls/FormControlsSample.cs @@ -118,7 +118,7 @@ public static void Run() code.AppendLine("End Sub"); module.Code = code.ToString(); - package.SaveAs(FileOutputUtil.GetFileInfo("26-FormControls.xlsm")); + package.SaveAs(FileUtil.GetCleanFileInfo("26-FormControls.xlsm")); } } @@ -128,13 +128,11 @@ private static ExcelWorksheet CreateFormSheet(ExcelPackage package) formSheet.Cells["A1"].Value = "Room booking"; formSheet.Cells["A1"].Style.Font.Size = 18; formSheet.Cells["A1"].Style.Font.Bold = true; - formSheet.Column(1).Width = 30; - formSheet.Column(2).Width = 60; + formSheet.Columns[1].Width = 30; + formSheet.Columns[2].Width = 60; formSheet.Cells.Style.Fill.SetBackground(Color.Gray); - for (int row = 1; row <= 18; row++) - { - formSheet.Row(row).Height = 25; - } + + formSheet.Rows[1, 18].Height = 25; return formSheet; } diff --git a/27-CustomNamedStyles/TableSlicerStyleSample.cs b/27-CustomNamedStyles/TableSlicerStyleSample.cs index ca69a6f..3857ae1 100644 --- a/27-CustomNamedStyles/TableSlicerStyleSample.cs +++ b/27-CustomNamedStyles/TableSlicerStyleSample.cs @@ -22,7 +22,7 @@ public static void Run(string connectionString) CreatePivotTableStyles(p); CreateSlicerStyles(p); - p.SaveAs(FileOutputUtil.GetFileInfo("27-TableAndSlicerStyles.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("27-TableAndSlicerStyles.xlsx")); } } diff --git a/28-Tables/Readme.md b/28-Tables/Readme.md index 257e913..f6d9944 100644 --- a/28-Tables/Readme.md +++ b/28-Tables/Readme.md @@ -1,9 +1,9 @@ # 28 - Tables sample These samples demonstrates how to work with tables in EPPlus. There are serveral more samples of this, so also checkout sample 4, 5 13, 18, 20, 24 First method shows how to add a calculated column to your table. -The second metod show how to style a table, add a custom total formula and adding rows. +The second method show how to style a table, add a custom total formula and adding rows. The third method adds a slicer to filter a table column. ### [TablesSample.cs](TablesSample.cs) - +### [SortingTablesSample.cs](SortingTablesSample.cs) --- [Back to overview](/Readme.md) \ No newline at end of file diff --git a/28-Tables/SortingTablesSample.cs b/28-Tables/SortingTablesSample.cs new file mode 100644 index 0000000..b4839de --- /dev/null +++ b/28-Tables/SortingTablesSample.cs @@ -0,0 +1,63 @@ +using OfficeOpenXml; +using OfficeOpenXml.Sorting; +using OfficeOpenXml.Table; +using System; +using System.Collections.Generic; +using System.Data.SQLite; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + /// + /// This sample demonstrates how to sort Excel tables in EPPlus. + /// + public static class SortingTablesSample + { + public static async Task RunAsync(string connectionString) + { + var file = FileUtil.GetCleanFileInfo("28-SortingTables.xlsx"); + using (ExcelPackage package = new ExcelPackage(file)) + { + // Sheet 1 + var sheet1 = package.Workbook.Worksheets.Add("Sheet1"); + sheet1.Cells["B1"].Value = "This table is sorted by country DESC, then name ASC, then orderValue ASC"; + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName, [Name], Email, c.Country, o.OrderId, orderdate, ordervalue, currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + var range = await sheet1.Cells["B3"].LoadFromDataReaderAsync(sqlCmd.ExecuteReader(), true, "Table1", TableStyles.Medium10); + range.AutoFitColumns(); + } + } + // sort this table by country DESC, then by sales persons name ASC, then by Order value ASC + var table1 = sheet1.Tables[0]; + table1.Sort(x => x.SortBy.ColumnNamed("country", eSortOrder.Descending) + .ThenSortBy.ColumnNamed("name") + .ThenSortBy.ColumnNamed("orderValue")); + + + // Sheet 2 + var sheet2 = package.Workbook.Worksheets.Add("Using custom list"); + sheet2.Cells["B1"].Value = "This table is sorted by country with a custom list, then name ASC, then orderValue ASC. The custom lists ensures that Greenland and Costa Rica comes first in the sort"; + using (var sqlConn = new SQLiteConnection(connectionString)) + { + sqlConn.Open(); + using (var sqlCmd = new SQLiteCommand("select CompanyName, [Name], Email, c.Country, o.OrderId, orderdate, ordervalue, currency from Customer c inner join Orders o on c.CustomerId=o.CustomerId inner join SalesPerson s on o.salesPersonId = s.salesPersonId ORDER BY 1,2 desc", sqlConn)) + { + var range = await sheet2.Cells["B3"].LoadFromDataReaderAsync(sqlCmd.ExecuteReader(), true, "Table2", TableStyles.Medium10); + range.AutoFitColumns(); + } + } + // sort this table by country ASC, then by sales persons name ASC, then by Order value ASC + var table2 = sheet2.Tables["Table2"]; + table2.Sort(x => x.SortBy.ColumnNamed("country", eSortOrder.Descending).UsingCustomList("Greenland", "Costa Rica") + .ThenSortBy.ColumnNamed("name") + .ThenSortBy.ColumnNamed("orderValue")); + + await package.SaveAsync(); + } + } + } +} diff --git a/28-Tables/TablesSample.cs b/28-Tables/TablesSample.cs index c6fc7fd..3a337e6 100644 --- a/28-Tables/TablesSample.cs +++ b/28-Tables/TablesSample.cs @@ -23,7 +23,7 @@ public static async Task RunAsync(string connectionString) await StyleTablesAsync(connectionString, p).ConfigureAwait(false); await CreateTableFilterAndSlicerAsync(connectionString, p).ConfigureAwait(false); - p.SaveAs(FileOutputUtil.GetFileInfo("28-Tables.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("28-Tables.xlsx")); } } /// diff --git a/29-ExternalLinks/ExternalLinksSample.cs b/29-ExternalLinks/ExternalLinksSample.cs index cd5e9e6..1257c4f 100644 --- a/29-ExternalLinks/ExternalLinksSample.cs +++ b/29-ExternalLinks/ExternalLinksSample.cs @@ -17,7 +17,7 @@ public static void Run() ReadFileWithExternalLink(); //Sample file 1 adds external links to another workbook. - var sampleFile1 = FileOutputUtil.GetFileInfo("29-ExternalLinks-1.xlsx"); + var sampleFile1 = FileUtil.GetCleanFileInfo("29-ExternalLinks-1.xlsx"); using (var p = new ExcelPackage(sampleFile1)) { @@ -38,7 +38,7 @@ public static void Run() /// private static void ReadFileWithExternalLink() { - var externalFile = FileInputUtil.GetFileInfo("29-ExternalLinks", "WorkbookWithExternalLinks.xlsx"); + var externalFile = FileUtil.GetFileInfo("29-ExternalLinks", "WorkbookWithExternalLinks.xlsx"); using (var p = new ExcelPackage(externalFile)) { //This worksheet contains references to an external workbook. @@ -72,7 +72,7 @@ private static void ReadFileWithExternalLink() //To avoid this behavior you can load the external workbook before doing the calculate. //This is only an issue in special cases where the function needs information not available in the cache, as for example hidden cells and numeric formats. var externalReference = p.Workbook.ExternalLinks[0].As.ExternalWorkbook; - p.Workbook.ExternalLinks.Directories.Add(FileInputUtil.GetSubDirectory("29-ExternalLinks","Data")); + p.Workbook.ExternalLinks.Directories.Add(FileUtil.GetSubDirectory("29-ExternalLinks","Data")); externalReference.Load(); ws.ClearFormulaValues(); @@ -91,7 +91,7 @@ private static void ReadFileWithExternalLink() private static void AddWorksheetWithExternalReferences(ExcelPackage p) { //Add a reference to the file created by sample 28. - var externalLinkFile = FileOutputUtil.GetFileInfo("28-Tables.xlsx", false); + var externalLinkFile = FileUtil.GetFileInfo("28-Tables.xlsx"); var externalWorkbook = p.Workbook.ExternalLinks.AddExternalWorkbook(externalLinkFile); var ws = p.Workbook.Worksheets.Add("Sheet1"); @@ -116,7 +116,7 @@ private static void AddWorksheetWithExternalReferences(ExcelPackage p) } private static void AddWorksheetWithExternalReferencesInFormulas(ExcelPackage p) { - var externalLinkFile = FileOutputUtil.GetFileInfo("01-GettingStarted.xlsx", false); + var externalLinkFile = FileUtil.GetFileInfo("01-GettingStarted.xlsx"); var externalWorkbook = p.Workbook.ExternalLinks.AddExternalWorkbook(externalLinkFile); var ws = p.Workbook.Worksheets.Add("Sheet2"); @@ -151,7 +151,7 @@ private static void BreakLinks(FileInfo sampleFile1) Console.WriteLine($"Now break links to the workbook {p.Workbook.ExternalLinks[0].As.ExternalWorkbook.File.FullName}"); p.Workbook.ExternalLinks.RemoveAt(0); - var newFile = FileOutputUtil.GetFileInfo("29-ExternalLinks-Link1Removed.xlsx", false); + var newFile = FileUtil.GetFileInfo("29-ExternalLinks-Link1Removed.xlsx"); p.SaveAs(newFile); } } diff --git a/30-SortingRanges/Readme.md b/30-SortingRanges/Readme.md deleted file mode 100644 index 9fcc681..0000000 --- a/30-SortingRanges/Readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# 30 - Sorting ranges -These samples demonstrates how to sort ranges with EPPlus. Contains one example for sorting top to bottom and one for left to right using a custom list. -### [SortingRangesSample.cs](SortingRangesSample.cs) ---- -[Back to overview](/Readme.md) \ No newline at end of file diff --git a/30-WorkingWithRanges/CopyRangeSample.cs b/30-WorkingWithRanges/CopyRangeSample.cs new file mode 100644 index 0000000..b4aec32 --- /dev/null +++ b/30-WorkingWithRanges/CopyRangeSample.cs @@ -0,0 +1,127 @@ +/************************************************************************************************* + Required Notice: Copyright (C) EPPlus Software AB. + This software is licensed under PolyForm Noncommercial License 1.0.0 + and may only be used for noncommercial purposes + https://polyformproject.org/licenses/noncommercial/1.0.0/ + + A commercial license to use this software can be purchased at https://epplussoftware.com + ************************************************************************************************* + Date Author Change + ************************************************************************************************* + 10/13/2021 EPPlus Software AB Initial release EPPlus 5 + *************************************************************************************************/ + +using OfficeOpenXml; +using System; +using System.Collections.Generic; +using System.Data.SQLite; +using System.Drawing; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public static class CopyRangeSample + { + //This sample demonstrates how to copy entire worksheet, ranges and how to exclude different cell properties. + public static void Run() + { + using (var p = new ExcelPackage()) + { + var sourceFile = FileUtil.GetFileInfo("08-Salesreport.xlsx"); + var sourcePackage = new ExcelPackage(sourceFile); + var sourceWs = sourcePackage.Workbook.Worksheets[0]; + + //Copy the entire source worksheet to a new worksheet. + CopyEntireWorksheet(p, sourceWs); + //Copy a range from the source worksheet to the new worksheet. + //This samples demonstrates how to exclude different options to exclude different parts of the cell properties + CopyRange(p, sourceWs); + //Copy a range with values only, removing any formula. + CopyValues(p); + //Copy styles + CopyStyles(p, sourceWs); + + p.SaveAs(FileUtil.GetCleanFileInfo("30-CopyRangeSamples.xlsx")); + } + } + + private static void CopyValues(ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("CopyValues"); + //Add some numbers and formulas and calculate the worksheet + ws.Cells["A1:A10"].FillNumber(1); + ws.Cells["B1:B9"].Formula = "A1+A2"; + ws.Cells["B10"].Formula = "Sum(B1:B9)"; + ws.Calculate(); + + //Now, copy the values starting at cell D1 without the formulas. + ws.Cells["A1:B10"].Copy(ws.Cells["D1"], ExcelRangeCopyOptionFlags.ExcludeFormulas); + } + + private static void CopyEntireWorksheet(ExcelPackage p, ExcelWorksheet sourceWs) + { + //To copy the entire worksheet just add the source worksheet as parameter 2 when adding the new worksheet. + p.Workbook.Worksheets.Add("CopySalesReport", sourceWs); + } + + private static void CopyRange(ExcelPackage p, ExcelWorksheet sourceWs) + { + var ws = p.Workbook.Worksheets.Add("CopyRangeOfReport"); + + //Use the first 10 rows of the sales report in sample 8 as the source. + var sourceRange = sourceWs.Cells["A1:G10"]; + + //Copy the source full range starting from C1. + //Copy always start from the top left cell of the destination range and copies the full range. + sourceRange.Copy(ws.Cells["C1"]); + + //Copy the same source range to C15 and exclude the hyperlinks. + //We also remove the Hyperlink style from the range containing the hyperlinks. + sourceRange.Copy(ws.Cells["C15"], ExcelRangeCopyOptionFlags.ExcludeHyperLinks); + ws.Cells["D19:D24"].StyleName = "Normal"; + + //Copy the values only, excluding merged cells, styles and hyperlinks. + sourceRange.Copy(ws.Cells["C30"], ExcelRangeCopyOptionFlags.ExcludeMergedCells, ExcelRangeCopyOptionFlags.ExcludeStyles , ExcelRangeCopyOptionFlags.ExcludeHyperLinks); + + //Copy styles and merged cells, excluding values and hyperlinks. + sourceRange.Copy(ws.Cells["C45"], ExcelRangeCopyOptionFlags.ExcludeValues, ExcelRangeCopyOptionFlags.ExcludeHyperLinks); + + ws.Cells.AutoFitColumns(); + } + private static void CopyStyles(ExcelPackage p, ExcelWorksheet sourceWs) + { + var ws = p.Workbook.Worksheets.Add("CopyStyles"); + + //Create a new random report + FillRangeWithRandomData(ws); + + //Copy the styles from the sales report. + //If the destination range is larger that the source range styles are filled down and right using the last column/row the source range of the source range. + sourceWs.Cells["A1:G5"].CopyStyles(ws.Cells["A1:G50"]); + + ws.Cells.AutoFitColumns(); + } + + private static void FillRangeWithRandomData(ExcelWorksheet ws) + { + ws.Cells["A1"].Value = "EPPlus"; + ws.Cells["A2"].Value = "New Random Report"; + ws.Cells["A4"].Value = "Color"; + ws.Cells["B4"].Value = "Category"; + ws.Cells["C4"].Value = "Country"; + ws.Cells["D4"].Value = "Id"; + ws.Cells["E4"].Value = "Date"; + ws.Cells["F4"].Value = "Amount"; + ws.Cells["G4"].Value = "Currency"; + + ws.Cells["A5:A50"].FillList(new string[] { "Red", "Green", "Blue", "Pink", "Black" }); + ws.Cells["B5:B50"].FillList(new string[] { "New", "Old" }); + ws.Cells["C5:C50"].FillList(new string[] { "Usa", "France", "India" }); + + ws.Cells["D5:D50"].FillNumber(1, 10); + ws.Cells["E5:E50"].FillDateTime(DateTime.Today); + ws.Cells["F5:F50"].FillNumber(1000, 50); + ws.Cells["G5:G50"].FillList(new string[] { "USD", "EUR", "INR" }); + } + } +} diff --git a/30-WorkingWithRanges/FillRangeSample.cs b/30-WorkingWithRanges/FillRangeSample.cs new file mode 100644 index 0000000..a340f6c --- /dev/null +++ b/30-WorkingWithRanges/FillRangeSample.cs @@ -0,0 +1,168 @@ +/************************************************************************************************* + Required Notice: Copyright (C) EPPlus Software AB. + This software is licensed under PolyForm Noncommercial License 1.0.0 + and may only be used for noncommercial purposes + https://polyformproject.org/licenses/noncommercial/1.0.0/ + + A commercial license to use this software can be purchased at https://epplussoftware.com + ************************************************************************************************* + Date Author Change + ************************************************************************************************* + 10/13/2021 EPPlus Software AB Initial release EPPlus 5 + *************************************************************************************************/ + +using OfficeOpenXml; +using System; +using System.Collections.Generic; + +namespace EPPlusSamples +{ + public static class FillRangeSample + { + public static void Run() + { + using (var p = new ExcelPackage()) + { + FillNumber(p); + FillDate(p); + FillList(p); + p.SaveAs(FileUtil.GetCleanFileInfo("30-FillRangeSamples.xlsx")); + } + } + /// + /// Several samples how to use the FillNumber method + /// + /// The package + private static void FillNumber(ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("FillNumber Samples"); + + ws.SetValue(1, 1, "FillNumber Default"); + ws.SetValue(2, 1, 50); + //Fill the range by adding 1 for each cell starting from the value in the top-left cell. + ws.Cells["A2:A20"].FillNumber(); + + ws.SetValue(1, 2, "FillNumber, Start 30, Step -2"); + //Fill the range by subtracting 2 from the initial value 30. + ws.Cells["B2:B20"].FillNumber(30, -2); + + ws.SetValue(1, 4, "FillNumber, Multiply add 5% row-wise"); + //Fill by starting with 100 and increase 5% for each cell. Fill to the left by row + ws.Cells["E1:AA1"].FillNumber(x => + { + x.CalculationMethod = eCalculationMethod.Multiply; + x.StartValue = 100; + x.StepValue = 1.05; + x.Direction = eFillDirection.Row; + }); + + ws.Cells["A1:D1"].Style.Font.Bold = true; + ws.Cells.AutoFitColumns(); + } + /// + /// Several samples how to use the FillDate method + /// + /// The package + private static void FillDate(ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("FillDateTime Samples"); + + //Fill dates starting from the value in the first cell. By default a 1 day increase is assumed and fill is performed per column downwards. + ws.SetValue("A1", "FillDateTime-Default"); + ws.SetValue("A2", new DateTime(2021, 1, 1)); + ws.Cells["A2:A60"].FillDateTime(); + + + ws.SetValue("B1", "FillDateTime-Step two months"); + //Fill dates using the starting value from a fixed start value instead of using the first cell. Increase with 2 months. + ws.Cells["B2:B60"].FillDateTime(new DateTime(2021, 6, 30), eDateTimeUnit.Month, 2); + + ws.Cells[2, 1, 60, 2].Style.Numberformat.Format = "yyyy-mm-dd"; + + ws.SetValue("C1", "FillDateTime-Month, exclude weekends and holidays"); + //Fill dates per last day of the quarter. If the start value is the last day of the month, this is used for all dates in the fill. + //This sample exclude weekends and adds some holiday dates. + //Column C2 and D2 are used as start values. + ws.Cells["C2"].Value = new DateTime(2015, 6, 30); + ws.Cells["D2"].Value = new DateTime(2009, 2, 28); + ws.Cells["C2:D60"].FillDateTime(x => + { + x.DateTimeUnit = eDateTimeUnit.Month; + x.StepValue = 3; + x.NumberFormat = "yyyy-mm-dd"; + x.SetExcludedWeekdays(DayOfWeek.Saturday, DayOfWeek.Sunday); //We exclude weekends. The day before is used instead. + x.SetExcludedDates( //These dates are also excluded. The day before is used instead. + new DateTime(2010, 12, 31), + new DateTime(2012, 12, 31), + new DateTime(2013, 12, 31), + new DateTime(2014, 12, 31), + new DateTime(2015, 12, 31), + new DateTime(2015, 12, 31), + new DateTime(2018, 12, 31), + new DateTime(2019, 12, 31), + new DateTime(2020, 12, 31), + new DateTime(2021, 12, 31), + new DateTime(2024, 12, 31), + new DateTime(2025, 12, 31), + new DateTime(2026, 12, 31), + new DateTime(2027, 12, 31), + new DateTime(2029, 12, 31) + ); + }); + + ws.SetValue("F1", "FillDateTime-By Row from Right-to-Left"); + //You can also fill row-wise and fill right-to-left. + //Note that as row 4 don't have a start value it's left blank in the fill. + //We also set an end value where the fill will stop. + ws.Cells["AA1"].Value = new DateTime(2030, 1, 1); + ws.Cells["AA2"].Value = new DateTime(2030, 1, 5); + ws.Cells["AA4"].Value = new DateTime(2030, 1, 10); + ws.Cells["H1:AA4"].FillDateTime(x => + { + x.Direction = eFillDirection.Row; + x.StartPosition = eFillStartPosition.BottomRight; + x.EndValue = new DateTime(2030, 1, 20); + x.NumberFormat = "yyyy-mm-dd"; + }); + ws.Cells["A1:F1"].Style.Font.Bold = true; + ws.Columns[1, 27].AutoFit(); + + } + /// + /// Several samples how to use the FillList method + /// + /// The package + private static void FillList(ExcelPackage p) + { + var ws = p.Workbook.Worksheets.Add("Fill List Samples"); + + var list = new[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; + ws.SetValue("A1", "FillList-Default"); + //FillList repeates the list. Default starts from the first item at position 0 + ws.Cells["A2:A20"].FillList(list); + + ws.SetValue("B1", "FillList-Start index 6"); + //Starts at position 6 in the list + ws.Cells["B2:B20"].FillList(list, x=> { x.StartIndex=6; }); + + ws.SetValue("E1", "FillList-Per row"); + //Fill per row + ws.Cells["F1:AA1"].FillList(list, x => + { + x.Direction = eFillDirection.Row; + }); + + ws.SetValue("C1", "FillList-Primes, bottom up"); + //Fill the list of primes starting from the bottom-up. + //We set the range to the size of the list so it's not repeated. + var primes = new List{ 2,5,7,11,13,17,19,23,29,997,1009 }; + ws.Cells[2,3,primes.Count+1, 3].FillList(primes, x => + { + x.NumberFormat = "#,##0"; + x.StartPosition = eFillStartPosition.BottomRight; + }); + ws.Cells["A1:E1"].Style.Font.Bold = true; + ws.Columns[1, 27].AutoFit(); + } + } +} \ No newline at end of file diff --git a/30-WorkingWithRanges/Readme.md b/30-WorkingWithRanges/Readme.md new file mode 100644 index 0000000..b12a178 --- /dev/null +++ b/30-WorkingWithRanges/Readme.md @@ -0,0 +1,10 @@ +# 30 - Working with ranges +These samples demonstrates how to fill, copy and sort ranges with EPPlus. +- Fill-Demonstrated the different Fill methods: FillNumber, FillDateTime and FillList +- Copy-Shows how to Copy an entire worksheet, copy a range and exclude some cell properties. Also shows how to copy styles. +- Sorting-Contains one example for sorting top to bottom and one for left to right using a custom list. +### [FillRangeSample.cs](FillRangeSample.cs) +### [CopyRangeSample.cs](CopyRangeSample.cs) +### [SortingRangesSample.cs](SortingRangesSample.cs) +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/30-SortingRanges/SortingRangesSample.cs b/30-WorkingWithRanges/SortingRangesSample.cs similarity index 97% rename from 30-SortingRanges/SortingRangesSample.cs rename to 30-WorkingWithRanges/SortingRangesSample.cs index 1c199ce..681ce48 100644 --- a/30-SortingRanges/SortingRangesSample.cs +++ b/30-WorkingWithRanges/SortingRangesSample.cs @@ -27,7 +27,7 @@ public static void Run() // Sort the range left to right by row 0 (using a custom list), then by row 1 sheet2.Cells["A3:K5"].Sort(x => x.SortLeftToRightBy.Row(0).UsingCustomList("S", "M", "L", "XL", "XXL").ThenSortBy.Row(1)); - p.SaveAs(FileOutputUtil.GetFileInfo("30-SortingRanges.xlsx")); + p.SaveAs(FileUtil.GetCleanFileInfo("30-SortingRanges.xlsx")); } } diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 474ea9a..0c2acba 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,8 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.7.0\lib\net45\EPPlus.dll + + packages\EPPlus.5.7.5.795-20211021-develop\lib\net45\EPPlus.dll packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll @@ -103,6 +103,7 @@ + @@ -127,9 +128,10 @@ - - - + + + + @@ -171,7 +173,7 @@ - + PreserveNewest diff --git a/FileInputUtil.cs b/FileInputUtil.cs deleted file mode 100644 index ae7a087..0000000 --- a/FileInputUtil.cs +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************************************************************* - Required Notice: Copyright (C) EPPlus Software AB. - This software is licensed under PolyForm Noncommercial License 1.0.0 - and may only be used for noncommercial purposes - https://polyformproject.org/licenses/noncommercial/1.0.0/ - - A commercial license to use this software can be purchased at https://epplussoftware.com - ************************************************************************************************* - Date Author Change - ************************************************************************************************* - 01/27/2020 EPPlus Software AB Initial release EPPlus 5 - *************************************************************************************************/using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace EPPlusSamples -{ - public class FileInputUtil - { - - /// - /// Returns a fileinfo with the full path of the requested file - /// - /// A subdirectory - /// - /// - public static FileInfo GetFileInfo(string directory, string file) - { - var rootDir = GetRootDirectory().FullName; - return new FileInfo(Path.Combine(rootDir, directory, file)); - } - - public static DirectoryInfo GetRootDirectory() - { - var currentDir = AppDomain.CurrentDomain.BaseDirectory; - while (!currentDir.EndsWith("bin")) - { - currentDir = Directory.GetParent(currentDir).FullName.TrimEnd('\\'); - } - return new DirectoryInfo(currentDir).Parent; - } - - public static DirectoryInfo GetSubDirectory(string directory, string subDirectory) - { - var currentDir = GetRootDirectory().FullName; - return new DirectoryInfo(Path.Combine(currentDir, directory, subDirectory)); - } - } -} diff --git a/FileOutputUtil.cs b/FileUtil.cs similarity index 60% rename from FileOutputUtil.cs rename to FileUtil.cs index 54af845..00534fc 100644 --- a/FileOutputUtil.cs +++ b/FileUtil.cs @@ -9,15 +9,12 @@ This software is licensed under PolyForm Noncommercial License 1.0.0 Date Author Change ************************************************************************************************* 01/27/2020 EPPlus Software AB Initial release EPPlus 5 - *************************************************************************************************/using System; -using System.Collections.Generic; + *************************************************************************************************/ +using System; using System.IO; -using System.Linq; -using System.Text; - namespace EPPlusSamples { - public class FileOutputUtil + public class FileUtil { static DirectoryInfo _outputDir = null; public static DirectoryInfo OutputDir @@ -35,15 +32,20 @@ public static DirectoryInfo OutputDir } } } - public static FileInfo GetFileInfo(string file, bool deleteIfExists = true) + public static FileInfo GetCleanFileInfo(string file) { var fi = new FileInfo(OutputDir.FullName + Path.DirectorySeparatorChar + file); - if (deleteIfExists && fi.Exists) + if (fi.Exists) { fi.Delete(); // ensures we create a new workbook } return fi; - } + } + public static FileInfo GetFileInfo(string file) + { + return new FileInfo(OutputDir.FullName + Path.DirectorySeparatorChar + file); + } + public static FileInfo GetFileInfo(DirectoryInfo altOutputDir, string file, bool deleteIfExists = true) { var fi = new FileInfo(altOutputDir.FullName + Path.DirectorySeparatorChar + file); @@ -64,5 +66,32 @@ internal static DirectoryInfo GetDirectoryInfo(string directory) } return di; } + /// + /// Returns a fileinfo with the full path of the requested file + /// + /// A subdirectory + /// + /// + public static FileInfo GetFileInfo(string directory, string file) + { + var rootDir = GetRootDirectory().FullName; + return new FileInfo(Path.Combine(rootDir, directory, file)); + } + + public static DirectoryInfo GetRootDirectory() + { + var currentDir = AppDomain.CurrentDomain.BaseDirectory; + while (!currentDir.EndsWith("bin")) + { + currentDir = Directory.GetParent(currentDir).FullName.TrimEnd('\\'); + } + return new DirectoryInfo(currentDir).Parent; + } + + public static DirectoryInfo GetSubDirectory(string directory, string subDirectory) + { + var currentDir = GetRootDirectory().FullName; + return new DirectoryInfo(Path.Combine(currentDir, directory, subDirectory)); + } } } diff --git a/Sample_Main.cs b/Sample_Main.cs index 8d04802..22b48a3 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -47,7 +47,7 @@ static async Task Main(string[] args) string connectionStr = "Data Source=EPPlusSample.sqlite;Version=3;"; //Set the output directory to the SampleApp folder where the app is running from. - FileOutputUtil.OutputDir = new DirectoryInfo($"{AppDomain.CurrentDomain.BaseDirectory}SampleApp"); + FileUtil.OutputDir = new DirectoryInfo($"{AppDomain.CurrentDomain.BaseDirectory}SampleApp"); // Sample 1 - simply creates a new workbook from scratch // containing a worksheet that adds a few numbers together @@ -65,13 +65,13 @@ static async Task Main(string[] args) //Sample 3 - Load and save using async methods Console.WriteLine("Running sample 3-Async-Await"); await UsingAsyncAwaitSample.RunAsync(connectionStr); - Console.WriteLine("Sample 3 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 3 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 4 - Shows a few ways to load data (Datatable, IEnumerable and more). Console.WriteLine("Running sample 4"); LoadingDataWithTablesSample.Run(); - Console.WriteLine("Sample 4 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 4 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 5 Loads two csv files into tables and creates an area chart and a Column/Line chart on the data. @@ -84,7 +84,7 @@ static async Task Main(string[] args) //Sample 6 Calculate - Shows how to calculate formulas in the workbook. Console.WriteLine("Sample 6 - Calculate formulas"); CalculateFormulasSample.Run(); - Console.WriteLine("Sample 6 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 6 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 7 @@ -118,7 +118,7 @@ static async Task Main(string[] args) //Sample 11 - Conditional Formatting Console.WriteLine("Running sample 11"); ConditionalFormatting.Run(); - Console.WriteLine("Sample 11 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 11 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 12 - Data validation @@ -130,32 +130,32 @@ static async Task Main(string[] args) //Sample 13 - Filter Console.WriteLine("Running sample 13-Filter"); await Filter.RunAsync(connectionStr); - Console.WriteLine("Sample 13 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 13 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 14 - Shapes & Images Console.WriteLine("Running sample 14-Shapes & Images"); ShapesAndImagesSample.Run(); - Console.WriteLine("Sample 14 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 14 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 15 - Themes and Chart styling Console.WriteLine("Running sample 15-Theme and Chart styling"); //Run the sample with the default office theme await ChartsAndThemesSample.RunAsync(connectionStr, - FileOutputUtil.GetFileInfo("15-ChartsAndThemes.xlsx"), null); + FileUtil.GetFileInfo("15-ChartsAndThemes.xlsx"), null); //Run the sample with the integral theme. Themes can be exported as thmx files from Excel and can then be applied to a package. await ChartsAndThemesSample.RunAsync(connectionStr, - FileOutputUtil.GetFileInfo("15-ChartsAndThemes-IntegralTheme.xlsx"), - FileInputUtil.GetFileInfo("15-ChartsAndThemes", "integral.thmx")); - Console.WriteLine("Sample 15 created {0}", FileOutputUtil.OutputDir.Name); + FileUtil.GetFileInfo("15-ChartsAndThemes-IntegralTheme.xlsx"), + FileUtil.GetFileInfo("15-ChartsAndThemes", "integral.thmx")); + Console.WriteLine("Sample 15 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 16 - Shows how to add sparkline charts. Console.WriteLine("Running sample 16-Sparklines"); SparkLinesSample.Run(); - Console.WriteLine("Sample 16 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 16 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); // Sample 17 - Creates a workbook based on a template. @@ -176,7 +176,7 @@ await ChartsAndThemesSample.RunAsync(connectionStr, //Sample 19 Swedish Quiz : Shows Encryption, workbook- and worksheet protection. Console.WriteLine("Running sample 19"); DrawingsSample.Run(); - Console.WriteLine("Sample 19 created: {0}", FileOutputUtil.OutputDir.FullName); + Console.WriteLine("Sample 19 created: {0}", FileUtil.OutputDir.FullName); Console.WriteLine(); //Sample 20 @@ -191,24 +191,24 @@ await ChartsAndThemesSample.RunAsync(connectionStr, //Sample 21 - Shows how to work with macro-enabled workbooks(VBA). Console.WriteLine("Running sample 21-VBA"); WorkingWithVbaSample.Run(); - Console.WriteLine("Sample 21 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 21 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 22 - Ignore cell errors using the IngnoreErrors Collection Console.WriteLine("Running sample 22-Suppress Errors"); IgnoreErrorsSample.Run(); - Console.WriteLine("Sample 22 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 22 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 23 - Comments and Threaded comments Console.WriteLine("Running sample 23-Comments/Notes and Threaded Comments"); CommentsSample.Run(); - Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 23 created {0}", FileUtil.OutputDir.Name); //Sample 24 - Table slicers and Pivot table slicers Console.WriteLine("Running sample 24-Table and Pivot table slicers"); SlicerSample.Run(connectionStr); - Console.WriteLine("Sample 23 created {0}", FileOutputUtil.OutputDir.Name); + Console.WriteLine("Sample 23 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); //Sample 25 - Import and Export DataTable @@ -241,8 +241,10 @@ await ChartsAndThemesSample.RunAsync(connectionStr, Console.WriteLine("Sample 29 finished."); Console.WriteLine(); - // Sample 30 - Sort ranges - Console.WriteLine("Running sample 30 - Sort ranges"); + // Sample 30 - Working with ranges + Console.WriteLine("Running sample 30 - Working with ranges"); + CopyRangeSample.Run(); + FillRangeSample.Run(); SortingRangesSample.Run(); Console.WriteLine("Sample 30 finished."); Console.WriteLine(); @@ -253,11 +255,11 @@ await ChartsAndThemesSample.RunAsync(connectionStr, } var prevColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine($"Genereted sample workbooks can be found in {FileOutputUtil.OutputDir.FullName}"); + Console.WriteLine($"Genereted sample workbooks can be found in {FileUtil.OutputDir.FullName}"); Console.ForegroundColor = prevColor; //Open the output folder - Process.Start(FileOutputUtil.OutputDir.FullName); + Process.Start(FileUtil.OutputDir.FullName); Console.WriteLine(); Console.WriteLine("Press the return key to exit..."); diff --git a/packages.config b/packages.config index 1094c3c..ddce41d 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - + From f77e4b48458d6854b3e77150ce88951ff07dc172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Thu, 21 Oct 2021 18:59:21 +0200 Subject: [PATCH 13/18] EPPlus 5.8.0 --- 25-ImportAndExportDataTable/Readme.md | 7 ------- EPPlus.Sample.NET.csproj | 4 ++-- packages.config | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) delete mode 100644 25-ImportAndExportDataTable/Readme.md diff --git a/25-ImportAndExportDataTable/Readme.md b/25-ImportAndExportDataTable/Readme.md deleted file mode 100644 index 44e8697..0000000 --- a/25-ImportAndExportDataTable/Readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# 25 - Import/export with DataTable -These samples demonstrates how to import and export data to/from a range to/from a DataTable. - -### [DataTableSample.cs](DataTableSample.cs) - ---- -[Back to overview](/Readme.md) \ No newline at end of file diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 0c2acba..24b10a2 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,8 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.7.5.795-20211021-develop\lib\net45\EPPlus.dll + + packages\EPPlus.5.8.0\lib\net45\EPPlus.dll packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll diff --git a/packages.config b/packages.config index ddce41d..eb732e6 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - + From 06eb33b8bca56dc9cee13a852e901026621bb712 Mon Sep 17 00:00:00 2001 From: JanKallman Date: Thu, 24 Feb 2022 16:31:33 +0100 Subject: [PATCH 14/18] Added html support for images --- 20-CreateFileSystemReport/CreateAFileSystemReport.cs | 2 ++ Sample_Main.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/20-CreateFileSystemReport/CreateAFileSystemReport.cs b/20-CreateFileSystemReport/CreateAFileSystemReport.cs index bd59640..5b2a85b 100644 --- a/20-CreateFileSystemReport/CreateAFileSystemReport.cs +++ b/20-CreateFileSystemReport/CreateAFileSystemReport.cs @@ -440,6 +440,8 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d if (fileIcon != null) { ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), fileIcon); + pic.Border.Width = 1; + pic.Border.LineStyle = eLineStyle.Solid; pic.SetPosition((int)20 * (row - 1) + 2, 0); } } diff --git a/Sample_Main.cs b/Sample_Main.cs index 22b48a3..698a11d 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -184,7 +184,7 @@ await ChartsAndThemesSample.RunAsync(connectionStr, //Parameter 2 is the directory to report. Parameter 3 is how deep the scan will go. Parameter 4 Skips Icons if set to true (The icon handling is slow) //This example demonstrates how to use outlines, tables,comments, shapes, pictures and charts. Console.WriteLine("Running sample 20"); - output = CreateAFileSystemReport.Run(new DirectoryInfo(System.Reflection.Assembly.GetEntryAssembly().Location).Parent, 5, true); + output = CreateAFileSystemReport.Run(new DirectoryInfo(System.Reflection.Assembly.GetEntryAssembly().Location).Parent, 5, false); Console.WriteLine("Sample 20 created:", output); Console.WriteLine(); From dda79a1a73253bfc5ed1b341b8446d42aa5520cc Mon Sep 17 00:00:00 2001 From: JanKallman Date: Tue, 12 Apr 2022 15:04:01 +0200 Subject: [PATCH 15/18] EPPlus 6.0.3 --- ...LoadingDataFromCollectionWithAttributes.cs | 43 ++++- 08-SalesReport/SalesReport.cs | 8 +- 14-ShapesAndImages/ShapesAndImagesSample.cs | 3 +- .../FXReportFromDatabase.cs | 21 ++- .../CreateAFileSystemReport.cs | 25 ++- 28-Tables/TablesSample.cs | 15 +- 31-HtmlExport/HtmlRangeExportSample.cs | 135 ++++++++++++++ 31-HtmlExport/HtmlTableExportSample.cs | 169 ++++++++++++++++++ 31-HtmlExport/Readme.md | 11 ++ 32-JsonExport/JsonExportSample.cs | 66 +++++++ 32-JsonExport/Readme.md | 7 + EPPlus.Sample.NET.csproj | 15 +- Readme.md | 4 +- Sample_Main.cs | 17 ++ packages.config | 4 +- 15 files changed, 521 insertions(+), 22 deletions(-) create mode 100644 31-HtmlExport/HtmlRangeExportSample.cs create mode 100644 31-HtmlExport/HtmlTableExportSample.cs create mode 100644 31-HtmlExport/Readme.md create mode 100644 32-JsonExport/JsonExportSample.cs create mode 100644 32-JsonExport/Readme.md diff --git a/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs index aa88d37..3ba76f5 100644 --- a/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs +++ b/04-LoadingData/LoadingDataFromCollectionWithAttributes.cs @@ -40,6 +40,36 @@ internal class Actor2 : Actor } + // classes used to demonstrate this functionality with a complex type property + [EpplusTable(TableStyle = TableStyles.Light14, PrintHeaders = true, AutofitColumns = true, AutoCalculate = true, ShowLastColumn = true)] + internal class Actor3 + { + [EpplusIgnore] + public int Id { get; set; } + + [EpplusNestedTableColumn(Order = 1)] + public ActorName Name { get; set; } + + [EpplusTableColumn(Order = 0, NumberFormat = "yyyy-MM-dd", TotalsRowLabel = "Total")] + public DateTime Birthdate { get; set; } + + [EpplusTableColumn(Order = 2, NumberFormat = "€#,##0.00", TotalsRowFunction = RowFunctions.Sum, TotalsRowNumberFormat = "€#,##0.00")] + public double Salary { get; set; } + + [EpplusTableColumn(Order = 3, NumberFormat = "0%", TotalsRowFormula = "Table1[[#Totals],[Tax amount]]/Table1[[#Totals],[Salary]]", TotalsRowNumberFormat = "0 %")] + public double Tax { get; set; } + } + + internal class ActorName + { + [EpplusTableColumn(Order = 3)] + public string LastName { get; set; } + [EpplusTableColumn(Order = 1, Header = "First name")] + public string FirstName { get; set; } + [EpplusTableColumn(Order = 2)] + public string MiddleName { get; set; } + } + public static class LoadingDataFromCollectionWithAttributes { public static void Run() @@ -59,6 +89,13 @@ public static void Run() new Actor2{ Salary = 315.34, Tax = 0.28, FirstName = "Lisa", MiddleName = "Maria", LastName = "Gonzales", Birthdate = new DateTime(1971, 10, 2)} }; + var complexTypeActors = new List + { + new Actor3{ Salary = 256.24, Tax = 0.21, Name = new ActorName{ FirstName="John", MiddleName="Bernhard", LastName="Doe" }, Birthdate = new DateTime(1950, 3, 15) }, + new Actor3{ Salary = 278.55, Tax = 0.23, Name = new ActorName{ FirstName="Sven", MiddleName="Bertil", LastName="Svensson" }, Birthdate = new DateTime(1962, 6, 10)}, + new Actor3{ Salary = 315.34, Tax = 0.28, Name = new ActorName{ FirstName="Lisa", MiddleName="Maria", LastName="Gonzales" }, Birthdate = new DateTime(1971, 10, 2)} + }; + using (var package = new ExcelPackage(FileUtil.GetCleanFileInfo("04-LoadFromCollectionAttributes.xlsx"))) { // using the Actor class above @@ -68,7 +105,11 @@ public static void Run() // using a subclass where we have overridden the EpplusTableAttribute (different TableStyle and highlight last column instead of the first). var subclassSheet = package.Workbook.Worksheets.Add("Using subclass with attributes"); subclassSheet.Cells["A1"].LoadFromCollection(subclassActors); - + + // using a subclass where we have overridden the EpplusTableAttribute (different TableStyle and highlight last column instead of the first). + var complexTypePropertySheet = package.Workbook.Worksheets.Add("Complex type property"); + complexTypePropertySheet.Cells["A1"].LoadFromCollection(complexTypeActors); + package.Save(); } } diff --git a/08-SalesReport/SalesReport.cs b/08-SalesReport/SalesReport.cs index f6d1dff..156c268 100644 --- a/08-SalesReport/SalesReport.cs +++ b/08-SalesReport/SalesReport.cs @@ -43,7 +43,7 @@ public static string Run(string connectionString) using (ExcelRange r = worksheet.Cells["A1:G1"]) { r.Merge = true; - r.Style.Font.SetFromFont(new Font("Britannic Bold", 22, FontStyle.Italic)); + r.Style.Font.SetFromFont("Britannic Bold", 22, false, true); r.Style.Font.Color.SetColor(Color.White); r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous; r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; @@ -53,7 +53,7 @@ public static string Run(string connectionString) using (ExcelRange r = worksheet.Cells["A2:G2"]) { r.Merge = true; - r.Style.Font.SetFromFont(new Font("Britannic Bold", 18, FontStyle.Italic)); + r.Style.Font.SetFromFont("Britannic Bold", 18, false, true); r.Style.Font.Color.SetColor(Color.Black); r.Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous; r.Style.Fill.PatternType = ExcelFillStyle.Solid; @@ -112,8 +112,8 @@ public static string Run(string connectionString) worksheet.Cells[startRow, 6, row - 1, 6].Style.Numberformat.Format = "[$$-409]#,##0"; //Set column width - worksheet.Columns[1].Width = 35; - worksheet.Columns[2, 3].Width = 28; + worksheet.Columns[1,3].Width = 35; + worksheet.Columns[2].Width = 28; worksheet.Columns[4].Width = 10; worksheet.Columns[5, 7].Width = 12; } diff --git a/14-ShapesAndImages/ShapesAndImagesSample.cs b/14-ShapesAndImages/ShapesAndImagesSample.cs index 365fa17..f4efe67 100644 --- a/14-ShapesAndImages/ShapesAndImagesSample.cs +++ b/14-ShapesAndImages/ShapesAndImagesSample.cs @@ -112,8 +112,7 @@ private static void FillAndColorSamples(ExcelPackage package) drawing.SetSize(250, 250); drawing.Fill.Style = eFillStyle.BlipFill; - var image = new Bitmap(FileUtil.GetFileInfo("14-ShapesAndImages", "EPPlusLogo.jpg").FullName); - drawing.Fill.BlipFill.Image = image; + drawing.Fill.BlipFill.Image.SetImage(FileUtil.GetFileInfo("14-ShapesAndImages", "EPPlusLogo.jpg")); drawing.Fill.BlipFill.Stretch = true; drawing.Text = "Blip Fill"; } diff --git a/17-FXReportFromDatabase/FXReportFromDatabase.cs b/17-FXReportFromDatabase/FXReportFromDatabase.cs index cb9846a..d7ccd0a 100644 --- a/17-FXReportFromDatabase/FXReportFromDatabase.cs +++ b/17-FXReportFromDatabase/FXReportFromDatabase.cs @@ -23,11 +23,20 @@ Date Author Change using System.Drawing; using System.Data.SQLite; using OfficeOpenXml.Drawing.Chart.Style; - +using System.Linq; namespace EPPlusSamples.FXReportFromDatabase { class FxReportFromDatabase { + public class FxRates + { + public DateTime? Date { get; set; } + public double UsdSek { get; set; } + public double UsdEur { get; set; } + public double UsdInr { get; set; } + public double UsdCny { get; set; } + public double UsdDkk { get; set; } + } /// /// This sample creates a new workbook from a template file containing a chart and populates it with Exchange rates from /// the database and set the three series on the chart. @@ -138,6 +147,16 @@ public static string Run(string connectionString) //Set the chart style chart.StyleManager.SetChartStyle(236); + var query = (from cell in ws.Cells["A22:A" + (row - 1).ToString()] + select new FxRates + { + Date = cell.GetCellValue(), + UsdSek = cell.GetCellValue(1), + UsdEur = cell.GetCellValue(2), + UsdInr = cell.GetCellValue(3), + UsdCny = cell.GetCellValue(4), + UsdDkk = cell.GetCellValue(5), + }).ToList(); } //Get the documet as a byte array from the stream and save it to disk. (This is useful in a webapplication) ... diff --git a/20-CreateFileSystemReport/CreateAFileSystemReport.cs b/20-CreateFileSystemReport/CreateAFileSystemReport.cs index 5b2a85b..9925147 100644 --- a/20-CreateFileSystemReport/CreateAFileSystemReport.cs +++ b/20-CreateFileSystemReport/CreateAFileSystemReport.cs @@ -205,7 +205,7 @@ private static void AddGraphs(ExcelPackage pck, int rows, string dir) using (ExcelRange r = ws.Cells["A1:O1"]) { r.Merge = true; - r.Style.Font.SetFromFont(new Font("Arial", 22, FontStyle.Regular)); + r.Style.Font.SetFromFont("Arial", 22); r.Style.Font.Color.SetColor(Color.White); r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous; r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; @@ -306,7 +306,7 @@ private static int AddStatRows(ExcelWorksheet ws, List lst, int startR using (ExcelRange r = ws.Cells[row, 1, row, 2]) { r.Merge = true; - r.Style.Font.SetFromFont(new Font("Arial", 16, FontStyle.Italic)); + r.Style.Font.SetFromFont("Arial", 16, false,true); r.Style.Font.Color.SetColor(Color.White); r.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.CenterContinuous; r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; @@ -321,7 +321,7 @@ private static int AddStatRows(ExcelWorksheet ws, List lst, int startR ws.Cells[row, 2].Value = propertyName; using (ExcelRange r = ws.Cells[row, 1, row, 2]) { - r.Style.Font.SetFromFont(new Font("Arial", 12, FontStyle.Bold)); + r.Style.Font.SetFromFont("Arial", 12, true); } row++; @@ -406,8 +406,13 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d //Add the icon as a picture if (icon != null) { - ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), icon); - pic.SetPosition((int)20 * (row - 1) + 2, 0); + using (var ms = new MemoryStream()) + { + icon.Save(ms, ImageFormat.Bmp); + ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms, ePictureType.Bmp); + pic.SetPosition((int)20 * (row - 1) + 2, 0); + + } } } ws.Cells[row, 2].Value = dir.Name; @@ -439,10 +444,12 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d ws.Rows[row].Height = height; if (fileIcon != null) { - ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), fileIcon); - pic.Border.Width = 1; - pic.Border.LineStyle = eLineStyle.Solid; - pic.SetPosition((int)20 * (row - 1) + 2, 0); + using (var ms = new MemoryStream()) + { + fileIcon.Save(ms, ImageFormat.Bmp); + ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms, ePictureType.Bmp); + pic.SetPosition((int)20 * (row - 1) + 2, 0); + } } } diff --git a/28-Tables/TablesSample.cs b/28-Tables/TablesSample.cs index 3a337e6..46ddc4a 100644 --- a/28-Tables/TablesSample.cs +++ b/28-Tables/TablesSample.cs @@ -96,7 +96,7 @@ private static async Task StyleTablesAsync(string connectionString, ExcelPackage var ws = p.Workbook.Worksheets.Add("StyleTables"); var range1 = await LoadDataAsync(connectionString, ws).ConfigureAwait(false); - + SetEmailAsHyperlink(range1); //Add the table and set some styles and properties. var tbl1 = ws.Tables.Add(range1, "StyleTable1"); tbl1.TableStyle = TableStyles.Medium24; @@ -133,6 +133,19 @@ private static async Task StyleTablesAsync(string connectionString, ExcelPackage tbl2.Range.AutoFitColumns(); } + + private static void SetEmailAsHyperlink(ExcelRangeBase range) + { + for(int row=1;row<=range.Rows;row++) + { + var cell = range.Offset(row, 2,1,1); + if (cell.Value != null) + { + cell.Hyperlink = new Uri($"mailto:{cell.Value}"); + } + } + } + /// /// This sample creates a table and a slicer. /// diff --git a/31-HtmlExport/HtmlRangeExportSample.cs b/31-HtmlExport/HtmlRangeExportSample.cs new file mode 100644 index 0000000..456f40b --- /dev/null +++ b/31-HtmlExport/HtmlRangeExportSample.cs @@ -0,0 +1,135 @@ +using OfficeOpenXml; +using OfficeOpenXml.Export.HtmlExport; +using System.Drawing; +using System.IO; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public static class HtmlRangeExportSample + { + //This sample demonstrates how to copy entire worksheet, ranges and how to exclude different cell properties. + //More advanced samples using charts and json exports are available in our samples web site available + //here: https://samples.epplussoftware.com/HtmlExport, https://samples.epplussoftware.com/JsonExport + public static async Task RunAsync() + { + var outputFolder = FileUtil.GetDirectoryInfo("HtmlOutput"); + + await ExportGettingStarted(outputFolder); + + ExportSalesReport(outputFolder); + + await ExcludeCssAsync(outputFolder); + + ExportMultipleRanges(outputFolder); + } + + private static async Task ExportGettingStarted(DirectoryInfo outputFolder) + { + //Start by using the excel file generated in sample 8 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("01-GettingStarted.xlsx"))) + { + var ws = p.Workbook.Worksheets["Inventory"]; + //Will create the html exporter for min and max bounds of the worksheet (ws.Dimensions) + var exporter = ws.Cells.CreateHtmlExporter(); + + //Get the html and styles in one call. + var html=await exporter.GetSinglePageAsync(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Range-01-GettingStarted.html", true).FullName, + html); + } + } + + private static void ExportSalesReport(DirectoryInfo outputFolder) + { + //Start by using the excel file generated in sample 8 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("08-Salesreport.xlsx"))) + { + var ws = p.Workbook.Worksheets["Sales"]; + var exporter = ws.Cells.CreateHtmlExporter(); //Will create the html exporter for min and max bounds of the worksheet (ws.Dimensions) + exporter.Settings.HeaderRows = 4; //We have three header rows. + exporter.Settings.TableId = "my-table"; //We can set an id of the worksheet if we want to use it in css or javascript. + + //By default EPPlus include the normal font in the css for the table. This can be tuned off and replaces by your own settings. + exporter.Settings.Css.IncludeNormalFont = false; + //AdditionalCssElements is a collection where you can add your own styles for the table. You can also clear default styles set by EPPlus. + exporter.Settings.Css.AdditionalCssElements.Add("font-family", "verdana"); + + //EPPlus will not set column width and row heights by default, as this doesn't go well with todays responsive designs. + //If you want fixed widths/heights set the proprties below to true... + //Note that individual width and height are set direcly on the colspan-elements and tr-elements. + //Default width and heights are set via the classes epp-dcw and epp-drh (with default StyleClassPrefix.). + exporter.Settings.SetColumnWidth = true; + exporter.Settings.SetRowHeight = true; + + //Get the html... + var htmlTable = exporter.GetHtmlString(); + //...and the styles + var cssTable = exporter.GetCssString(); + + //EPPlus will not add the Excel grid lines, but you can easily add your own in the css... + cssTable += "#my-table th,td {border:solid thin lightgray}"; + + var html = $"{htmlTable}"; + + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Range-02-Salesreport.html", true).FullName, + html); + } + } + private static async Task ExcludeCssAsync(DirectoryInfo outputFolder) + { + //Start by using the excel file generated in sample 20 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("20-CreateAFileSystemReport.xlsx"))) + { + var ws = p.Workbook.Worksheets[0]; + var range = ws.Cells[1, 1, 5, ws.Dimension.End.Column]; + + var exporter = range.CreateHtmlExporter(); + //Css can be excluded on style level, if you don't want some style or you want to add your own. + exporter.Settings.Css.CssExclude.Font = eFontExclude.Bold | eFontExclude.Italic | eFontExclude.Underline; + + var html = await exporter.GetSinglePageAsync(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Range-03-ExcludeCss.html", true).FullName, + html); + } + } + private static void ExportMultipleRanges(DirectoryInfo outputFolder) + { + //Start by using the excel file generated in sample 15 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("15-ChartsAndThemes.xlsx"))) + { + //Now we will use the sample 15 and read two ranges from two different worksheets and combine them to use the same CSS. + //To do so we create an HTML exporter on the workbook level and adds the ranges we want to use. + var ws3D = p.Workbook.Worksheets["3D Charts"]; + var wsStock = p.Workbook.Worksheets["Stock Chart"]; + + //We mark the top and bottom two values with red and green. + ws3D.Cells["B13,B7"].Style.Fill.SetBackground(Color.Green); + ws3D.Cells["B14,B5"].Style.Fill.SetBackground(Color.Red); + + //We mark the top and bottom two rows with red and green. + wsStock.Cells["A3:E4"].Style.Fill.SetBackground(Color.Green); + wsStock.Cells["A7:E8"].Style.Fill.SetBackground(Color.Red); + + var tblChartData = p.Workbook.Worksheets["ChartData"].Tables[0]; + + //Create the exporter. The workbook exporter exports ranges and tables, if the range corresponds to the table range.. + var rngExporter = p.Workbook.CreateHtmlExporter( + ws3D.Cells["A1:D16"], + wsStock.Cells["A1:E11"], + tblChartData.Range); //If you want to export a table, the exact table range must be used. + + //Get the html for the ranges in the HTML. The argument index referece to the ranges supplied when creating the exporter. + var html3D = rngExporter.GetHtmlString(0); + var htmlStock = rngExporter.GetHtmlString(1); + var tblHtml = rngExporter.GetHtmlString(2); + var css = rngExporter.GetCssString(); + + //We also exports a table and merge the css the range css. + var htmlTemplate = "\r\n\r\n\r\n\r\n{1}
{2}
{3}\r\n"; + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Range-04-MultipleRanges.html", true).FullName, + string.Format(htmlTemplate, css, html3D, htmlStock, tblHtml)); + } + } + } +} \ No newline at end of file diff --git a/31-HtmlExport/HtmlTableExportSample.cs b/31-HtmlExport/HtmlTableExportSample.cs new file mode 100644 index 0000000..8ec1692 --- /dev/null +++ b/31-HtmlExport/HtmlTableExportSample.cs @@ -0,0 +1,169 @@ +using OfficeOpenXml; +using OfficeOpenXml.Export.HtmlExport; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace EPPlusSamples +{ + public static class HtmlTableExportSample + { + //This sample demonstrates how to export html from a table. + //More advanced samples using charts and json exports are available in our samples web site available + //here: https://samples.epplussoftware.com/HtmlExport, https://samples.epplussoftware.com/JsonExport + public static void Run() + { + var outputFolder = FileUtil.GetDirectoryInfo("HtmlOutput"); + //Start by using the excel file generated in sample 28 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("28-Tables.xlsx"))) + { + var wsSimpleTable = p.Workbook.Worksheets["SimpleTable"]; + + ExportSimpleTable1(outputFolder, wsSimpleTable); + ExportSimpleTable2(outputFolder, wsSimpleTable); + + var wsStyleTables = p.Workbook.Worksheets["StyleTables"]; + ExportStyleTables(outputFolder, wsStyleTables); + + //This samples exports the filtered table from the slicer sample. + var wsSlicer = p.Workbook.Worksheets["Slicer"]; + ExportSlicerTables1(outputFolder, wsSlicer); + + //Exports three tables and combine the html and css + ExportMultipleTables(outputFolder); + } + } + private static void ExportSimpleTable1(DirectoryInfo outputFolder, ExcelWorksheet wsSimpleTable) + { + var table1 = wsSimpleTable.Tables[0]; + //Create the exporter for the table. + var htmlExporter = table1.CreateHtmlExporter(); + + //EPPlus will minify the css and html by default, but for this sample we want it easier to read. + htmlExporter.Settings.Minify = false; + + // The GetSinglePage method generates en single page. You can also add a string parameter with your own HTML where where the styles and table html is inserted. + var fullHtml = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-01-Table1_SinglePage.html", true).FullName, + fullHtml); + + //In most cases you want to keep the html and the styles separated, so you will retrive the html and the css in separate calls... + var tableHtml = htmlExporter.GetHtmlString(); + var tableCss = htmlExporter.GetCssString(); + + //First create the html file and reference the the css. + var html = $"{tableHtml}"; + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-01-Table1.html", true).FullName, + html); + + //The css is written to a separate file. + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-01-Table1.css", true).FullName, tableCss); + } + private static void ExportSimpleTable2(DirectoryInfo outputFolder, ExcelWorksheet wsSimpleTable) + { + var table2 = wsSimpleTable.Tables[1]; + + //Create the exporter for the table. + var htmlExporter = table2.CreateHtmlExporter(); + //EPPlus will generate Accessibility and data attributes by default, but you can turn it of in the settings. + htmlExporter.Settings.Accessibility.TableSettings.AddAccessibilityAttributes = false; + htmlExporter.Settings.RenderDataAttributes = false; + + var html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-02-Table2.html", true).FullName, + html); + + //We can also change the table style to get a different styling. + //Here we change to Medium15... + table2.TableStyle = OfficeOpenXml.Table.TableStyles.Medium15; + html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-02-table2_Medium15.html", true).FullName, + html); + + //...Here we use Dark2... + table2.TableStyle = OfficeOpenXml.Table.TableStyles.Dark2; + html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-02-table2_Dark2.html", true).FullName, + html); + } + + private static void ExportStyleTables(DirectoryInfo outputFolder, ExcelWorksheet wsStyleTables) + { + //The last row of the cell contains uncalculated cell (they calculate when opened in Excel), + //but in EPPlus we need to calculate them first to get a result in cell A254 in the totals row. + wsStyleTables.Calculate(); + + var table1 = wsStyleTables.Tables[0]; + var htmlExporter = table1.CreateHtmlExporter(); + + //This sample exports the table as well as some individually cell styles. The headers have font italic and the totals row has a custom formatted text. + //Also note that Column 2 has hyper links create for the mail addresses. + var html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-02-Styling_table1_with_hyperlinks.html", true).FullName, + html); + + var table2 = wsStyleTables.Tables[1]; + htmlExporter = table2.CreateHtmlExporter(); + + //Table 2 contains a custom table style. + html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-02-Styling_table2.html", true).FullName, + html); + } + private static void ExportSlicerTables1(DirectoryInfo outputFolder, ExcelWorksheet wsSlicer) + { + var table1 = wsSlicer.Tables[0]; + var htmlExporter = table1.CreateHtmlExporter(); + + //This sample exports the table filtered by the selection in the slicer (that applies the filter on the table). + //By default EPPlus will remove hidden rows. + var html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-03-Slicer.html", true).FullName, + html); + + //You can change this option by setting eHiddenState.Include in the settings. + //You can also set the it to eHiddenState.IncludeButHide if you want to apply your own filtering. + htmlExporter.Settings.HiddenRows = eHiddenState.Include; + html = htmlExporter.GetSinglePage(); + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-03-Slicer_table_all_rows.html", true).FullName, + html); + } + private static void ExportMultipleTables(DirectoryInfo outputFolder) + { + using (var p = new ExcelPackage(FileUtil.GetFileInfo("04-LoadingData.xlsx"))) + { + //Now we will use the third worksheet from sample 4, that contains three tables with different styles. + var wsList = p.Workbook.Worksheets["FromList"]; + + var tbl1 = wsList.Tables[0]; + var exporter1 = tbl1.CreateHtmlExporter(); + var tbl1Html = exporter1.GetHtmlString(); + var tbl1Css = exporter1.GetCssString(); + + var tbl2 = wsList.Tables[1]; + var exporter2 = tbl2.CreateHtmlExporter(); + var tbl2Html = exporter2.GetHtmlString(); + //We have already exported the css once, so we don't want shared css classes to be added again. + exporter2.Settings.Css.IncludeSharedClasses = false; + var tbl2Css = exporter2.GetCssString(); + + var tbl3 = wsList.Tables[2]; + var exporter3 = tbl3.CreateHtmlExporter(); + var tbl3Html = exporter3.GetHtmlString(); + exporter3.Settings.Css.IncludeSharedClasses = false; + + var tbl3Css = exporter3.GetCssString(); + + //As the tables have different table styles we add all of the css's. + //If multiple tables have the same table style, you should only add one of them. + var css = tbl1Css + tbl2Css + tbl3Css; + + var htmlTemplate = "\r\n\r\n\r\n\r\n{1}
{2}
{3}\r\n"; + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "Table-04-MultipleTables.html", true).FullName, + string.Format(htmlTemplate, css, tbl1Html, tbl2Html, tbl3Html)); + } + } + + } +} \ No newline at end of file diff --git a/31-HtmlExport/Readme.md b/31-HtmlExport/Readme.md new file mode 100644 index 0000000..7208216 --- /dev/null +++ b/31-HtmlExport/Readme.md @@ -0,0 +1,11 @@ +# 31 - Html export from ranges and tables +These samples demonstrates Export ranges and tables as HTML in EPPlus. +EPPlus supports exporting cell values, styles, and hyper links as html. +EPPlus also exports tables with there selected table style, both build-in table styles and custom table styles are supported. +More advanced samples using charts and json exports are available in our samples web site available +here: https://samples.epplussoftware.com/HtmlExport, https://samples.epplussoftware.com/JsonExport + +### [HtmlTableExportSample.cs](HtmlTableExportSample.cs) +### [HtmlRangeExportSample.cs](HtmlRangeExportSample.cs) +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/32-JsonExport/JsonExportSample.cs b/32-JsonExport/JsonExportSample.cs new file mode 100644 index 0000000..925bb3d --- /dev/null +++ b/32-JsonExport/JsonExportSample.cs @@ -0,0 +1,66 @@ +using OfficeOpenXml; +using System.IO; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public static class JsonExportSample + { + //This sample demonstrates how to export html from a table. + //More advanced samples using charts and json exports are available in our samples web site available + //here: https://samples.epplussoftware.com/JsonExport + public static async Task RunAsync() + { + var outputFolder = FileUtil.GetDirectoryInfo("JsonOutput"); + + //Start by using the excel file generated in sample 28 + using (var p = new ExcelPackage(FileUtil.GetFileInfo("28-Tables.xlsx"))) + { + var wsSimpleTable = p.Workbook.Worksheets["SimpleTable"]; + + ExportTable1(outputFolder, wsSimpleTable); + + var wsStyleTables = p.Workbook.Worksheets["StyleTables"]; + await ExportTableWithHyperlink(outputFolder, wsStyleTables); + } + } + + private static void ExportTable1(DirectoryInfo outputFolder, ExcelWorksheet wsSimpleTable) + { + var table1 = wsSimpleTable.Tables[0]; + + //First export the table directly from the table object. + //When exporting a table the data type is set on the column. + var json = table1.ToJson(x => + { + x.Minify = false; + }); + + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "TableSample1_As_Table.json", true).FullName, json); + + //When exporting the range data types are set on the cell level. + //You can alter this by AddDataTypesOn, --> x.AddDataTypesOn=eDataTypeOn.OnColumn + json = table1.Range.ToJson(x => + { + x.Minify = false; + }); + + File.WriteAllText(FileUtil.GetFileInfo(outputFolder, "TableSample1_As_Range.json", true).FullName, json); + } + private static async Task ExportTableWithHyperlink(DirectoryInfo outputFolder, ExcelWorksheet wsStyleTables) + { + var table1 = wsStyleTables.Tables[0]; + + + using (var fs = new FileStream(FileUtil.GetFileInfo(outputFolder, "TableSample2_hyperlinks.json", true).FullName, FileMode.Create, FileAccess.Write)) + { + await table1.SaveToJsonAsync(fs, x => + { + x.AddDataTypesOn = eDataTypeOn.NoDataTypes; //Skip data types. + x.Minify = false; + }); + fs.Close(); + } + } + } +} \ No newline at end of file diff --git a/32-JsonExport/Readme.md b/32-JsonExport/Readme.md new file mode 100644 index 0000000..66dcb67 --- /dev/null +++ b/32-JsonExport/Readme.md @@ -0,0 +1,7 @@ +# 32 - Json export +This samples demonstrates Export ranges and tables as json in EPPlus. +Json export for ranges and table looks slightly different. +EPPlus also exports tables with there selected table style, both build-in table styles and custom table styles are supported. +### [JsonExportSample.cs](JsonExportSample.cs) +--- +[Back to overview](/Readme.md) \ No newline at end of file diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index 24b10a2..a65dd61 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -42,8 +42,14 @@ packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.5.8.0\lib\net45\EPPlus.dll + + packages\EPPlus.6.0.3\lib\net452\EPPlus.dll + + + packages\EPPlus.Interfaces.6.0.0\lib\net452\EPPlus.Interfaces.dll + + + packages\EPPlus.System.Drawing.6.0.0\lib\net452\EPPlus.System.Drawing.dll packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll @@ -131,6 +137,9 @@ + + + @@ -174,6 +183,8 @@ + + PreserveNewest diff --git a/Readme.md b/Readme.md index a047e66..49c16d3 100644 --- a/Readme.md +++ b/Readme.md @@ -35,7 +35,9 @@ The solution can be opened in Visual Studio for Windows. |27|[Custom styles for tables and slicers](/27-CustomNamedStyles)|Sample showing how to create custom styles from tables, pivot tables and slicers. |28|[Tables](/28-Tables)|Sample showing how to work with tables. |29|[External links](/29-ExternalLinks)|Shows how to work with links to external workbooks -|30|[Sorting Ranges](/30-SortingRanges)|Shows how to work with the Sort method for ranges and tables +|30|[Sorting Ranges](/30-WorkingWithRanges)|Shows how to work with the Sort method for ranges and tables +|31|[Html Export](/31-HtmlExport)|Shows how to export tables and ranges to HTML +|32|[Json Export](/32-JsonExport)|Shows how to export tables and ranges to JSON ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. diff --git a/Sample_Main.cs b/Sample_Main.cs index 698a11d..ad68a18 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -248,6 +248,23 @@ await ChartsAndThemesSample.RunAsync(connectionStr, SortingRangesSample.Run(); Console.WriteLine("Sample 30 finished."); Console.WriteLine(); + + // Sample 31 - Html Export + //This sample shows basic html export functionality. + //For more advanced samples using charts see https://samples.epplussoftware.com/HtmlExport + Console.WriteLine("Running sample 31 - Html export"); + HtmlTableExportSample.Run(); + await HtmlRangeExportSample.RunAsync(); + Console.WriteLine("Sample 31 finished."); + Console.WriteLine(); + + //Sample 32 - Json Export + //This sample shows the json export functionality. + //For more a samples exporting to chart librays see https://samples.epplussoftware.com/JsonExport + Console.WriteLine("Running sample 32 - json export"); + await JsonExportSample.RunAsync(); + Console.WriteLine("Sample 32 finished."); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index eb732e6..66597d5 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,9 @@  - + + + From e11152e4b71c44557fe8a17a95202a5d6038c4fc Mon Sep 17 00:00:00 2001 From: JanKallman Date: Thu, 3 Nov 2022 10:43:29 +0100 Subject: [PATCH 16/18] EPPlus 6.1.0 - Updated sample 20 with new outline grouping methods and sample 21-Add sample to sign a workbook with the new vba signatures --- 08-SalesReport/SalesReport.cs | 2 + .../CreateAFileSystemReport.cs | 50 ++++--- 21-VBA/SampleCertificate.pfx | Bin 0 -> 2796 bytes 21-VBA/SigningYourVBAProject.cs | 48 ++++++ 33-ToCollection/Readme.md | 6 + 33-ToCollection/ToCollectionClasses.cs | 90 +++++++++++ 33-ToCollection/ToCollectionSample.cs | 140 ++++++++++++++++++ App.config | 18 ++- EPPlus.Sample.NET.csproj | 66 ++++++--- Readme.md | 3 +- Sample_Main.cs | 11 +- packages.config | 25 ++-- 12 files changed, 398 insertions(+), 61 deletions(-) create mode 100644 21-VBA/SampleCertificate.pfx create mode 100644 21-VBA/SigningYourVBAProject.cs create mode 100644 33-ToCollection/Readme.md create mode 100644 33-ToCollection/ToCollectionClasses.cs create mode 100644 33-ToCollection/ToCollectionSample.cs diff --git a/08-SalesReport/SalesReport.cs b/08-SalesReport/SalesReport.cs index 156c268..5695a8a 100644 --- a/08-SalesReport/SalesReport.cs +++ b/08-SalesReport/SalesReport.cs @@ -36,6 +36,8 @@ public static string Run(string connectionString) var namedStyle = xlPackage.Workbook.Styles.CreateNamedStyle("HyperLink"); namedStyle.Style.Font.UnderLine = true; namedStyle.Style.Font.Color.SetColor(Color.Blue); + namedStyle.BuildInId = 8; //This is the id for the build in HyperLink style. + const int startRow = 5; int row = startRow; //Create Headers and format them diff --git a/20-CreateFileSystemReport/CreateAFileSystemReport.cs b/20-CreateFileSystemReport/CreateAFileSystemReport.cs index 9925147..d4a63de 100644 --- a/20-CreateFileSystemReport/CreateAFileSystemReport.cs +++ b/20-CreateFileSystemReport/CreateAFileSystemReport.cs @@ -98,8 +98,7 @@ public static string Run(DirectoryInfo dir, int depth, bool skipIcons) int row = 2; //Load the directory content to sheet 1 - row = AddDirectory(ws, dir, row, height, 0, skipIcons); - + row = AddDirectory(ws, dir, row, height, skipIcons); ws.OutLineSummaryBelow = false; //Format columns @@ -111,8 +110,8 @@ public static string Run(DirectoryInfo dir, int depth, bool skipIcons) var shape = ws.Drawings.AddShape("txtDesc", eShapeStyle.Rect); shape.SetPosition(1, 5, 6, 5); shape.SetSize(400, 200); - - shape.Text = "This example demonstrates how to create various drawing objects like pictures, shapes and charts.\n\r\n\rThe first sheet contains all subdirectories and files with an icon, name, size and dates.\n\r\n\rThe second sheet contains statistics about extensions and the top-10 largest files."; + shape.EditAs = eEditAs.Absolute; + shape.Text = "This example demonstrates how to create various drawing objects like pictures, shapes and charts.\n\r\n\rThe first sheet contains all subdirectories and files with an icon, name, size and dates.\r\n\r\nThe second sheet contains statistics about extensions and the top-10 largest files."; shape.Fill.Style = eFillStyle.SolidFill; shape.Fill.Color = Color.DarkSlateGray; shape.Fill.Transparancy = 20; @@ -129,12 +128,22 @@ public static string Run(DirectoryInfo dir, int depth, bool skipIcons) //Add the graph sheet AddGraphs(pck, row, dir.FullName); - //Add a HyperLink to the statistics sheet. - var namedStyle = pck.Workbook.Styles.CreateNamedStyle("HyperLink"); //This one is language dependent - namedStyle.Style.Font.UnderLine = true; - namedStyle.Style.Font.Color.SetColor(Color.Blue); - ws.Cells["K13"].Hyperlink = new ExcelHyperLink("Statistics!A1", "Statistics"); - ws.Cells["K13"].StyleName = "HyperLink"; + + //Add a drawing with a HyperLink to the statistics sheet. + //We add the hyperlink as a drawing here, as we don't want it to move when we expand and collapse rows.. + var hl =ws.Drawings.AddShape("HyperLink", eShapeStyle.Rect); + hl.Hyperlink = new ExcelHyperLink("Statistics!A1", "Statistics"); + hl.SetPosition(13, 0, 9, 0); + hl.SetSize(70, 30); + hl.EditAs = eEditAs.Absolute; + hl.Border.Fill.Style = eFillStyle.NoFill; + hl.Fill.Style = eFillStyle.NoFill; + hl.Text = "Statistics"; + hl.Font.UnderLine = eUnderLineType.Single; + hl.Font.Fill.Color = Color.Blue; + + // Collaps children to level 1 for each row under the root. + ws.Rows[2].SetVisibleOutlineLevel(1); //Printer settings ws.PrinterSettings.FitToPage = true; @@ -394,7 +403,7 @@ private static void AlterColor(ExcelWorksheet ws, int row) } } - private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, double height, int level, bool skipIcons) + private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, double height, bool skipIcons) { //Get the icon as a bitmap Console.WriteLine("Directory " + dir.Name); @@ -409,9 +418,8 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d using (var ms = new MemoryStream()) { icon.Save(ms, ImageFormat.Bmp); - ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms, ePictureType.Bmp); + ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms); pic.SetPosition((int)20 * (row - 1) + 2, 0); - } } } @@ -420,17 +428,15 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d ws.Cells[row, 5].Value = dir.LastAccessTime; ws.Cells[row, 2, row, 5].Style.Font.Bold = true; - //Sets the outline depth - ws.Rows[row].OutlineLevel = level; int prevRow = row; row++; //Add subdirectories foreach (DirectoryInfo subDir in dir.GetDirectories()) { - if (level < _maxLevels) + if (ws.Rows[prevRow].OutlineLevel < _maxLevels) { - row = AddDirectory(ws, subDir, row, height, level + 1, skipIcons); + row = AddDirectory(ws, subDir, row, height, skipIcons); } } @@ -447,7 +453,7 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d using (var ms = new MemoryStream()) { fileIcon.Save(ms, ImageFormat.Bmp); - ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms, ePictureType.Bmp); + ExcelPicture pic = ws.Drawings.AddPicture("pic" + (row).ToString(), ms); pic.SetPosition((int)20 * (row - 1) + 2, 0); } } @@ -458,13 +464,17 @@ private static int AddDirectory(ExcelWorksheet ws, DirectoryInfo dir, int row, d ws.Cells[row, 4].Value = file.CreationTime; ws.Cells[row, 5].Value = file.LastAccessTime; - ws.Rows[row].OutlineLevel = level+1; - AddStatistics(file); row++; } + //If the directory has children, group them. The Group method adds one to the Outline level. + if (prevRow < row - 1) + { + ws.Rows[prevRow + 1, row - 1].Group(); + } + //Add a subtotal for the directory if (row -1 > prevRow) { diff --git a/21-VBA/SampleCertificate.pfx b/21-VBA/SampleCertificate.pfx new file mode 100644 index 0000000000000000000000000000000000000000..2e03b01db8667ece4112c10306ee06e5b062c194 GIT binary patch literal 2796 zcmai$c{r3^AII-uj4_OujBMF52$Qi(7$UMXWU`bcThnBz(8ykm3}q{iB_`R5tSO{L zGw~p43@ZCRl1$W)cBG)!3aU1|BK)e-~%vwAp+i%qo6aqV2~PE#3W!6 zZsc(XTv!s2$8nmq0h7U#Eb6dVfh#)FPP*syV$w)ceCh1xzFwFiGf37@C3n)$J0mTD zZKsb5bU}1TeT2Wt3IS8I_s*}&XvE|tpDD6vkhgekw6Hzi@l8UYbZjcZ^@u42?wQKG zN1|_O1~W{|R8MVL@KaFpaz5J%){aFfAp@;x3i!7+LkS&T#RL0F+*yp*4TydPFZuCa z^<(uItDm>cT#nc_Cb36`mr(m(4SLVMq}VOYab`X%`6-%JzR%ts&m-k`OG&NO`}|S& z)h@-OI|_f^YUv9FJ~{NHhyuL#eEB=Z-Qpv#q*@ z7ud6_jO#Ox0`|Wd>|RmDzCVxE0aI(4}dJ3?pu2 zKA>;H!Q~l@wNSPMq{lkq(^t;~yPJ!=En+8rbsM+4!psv3))hWkiz{#39e_Araaf2f zPT1Irn(8uW@|2>gMqpD0MjA!F>)F?M@6trc#H*ML7+FgH`fsMHsolO&>013n9o*WRcQXGS;Ou=M-BsTy`O%-ey( z+AmWcJ;>*_pCzUFhzJ@~EoLKo=qCp=F63Y6xY_hEO!?ii<567u z5ozUd(1O7UnC_&JdYq589dLWWYbjS8Tv(k0>(bg3nrStDZZ-*3STMe94*Rnat&tRO z_$V~f?@f>Mmu8EI$jOvbxPVkN4S!z91ESA5{-l^)kw<$g_Q3A9gzeT2r^ZZpn4 z){PXY@&{deiyB*0{o*3QBgZ#kIPMdfr88K7nh%Pojvg+4NyX{WE zygZH`&7Rh$Q}C2%46nIH1ECYjoY6trw%69Y6Zw4qYd`F1iEvZPIBja9HN(s|n!%tR zh=gf8D^SEwJiC=9-8yU%<1~S!^0Msj=tQvW^EijbFGkh*OBNk`fEe8$9q6^Vuli#C zt`pWWX`YTtF$lvK4s^}>teU{`qMX2c-&T2|4kzRA?}OUW!^eM^b^K)NAE}Pas!&X9 ziX)hFA}nc4JDjnvWvcBAZ_Ji8MG-fE004~VKTu4|Q5FYW0?q(vzyR>&&idR@ zhg%1^1OxbRi7vO(1q`|6$L$URTHNO^Rp-|}!Y_|5;Ll|~+#NoD#j8U=U=Z0r6!a_p z7;ug&gaQ|UFm4gJuagJxe|ML;rciE#JYdHiBY!EExLPQepZ&!he>uas8UEaLD25Ey z{{8*@kU}ze9~a5-fB^0!@s9%fx4Yxrwru5h`o_$^-W~e$GE>aOs7xUCU~{J{UHK}R zxAxKjseZR;VvpB)5}&#_P%mRCcmvsWeaFBlmkg)cN^~-vRNt^G&fW{fi5H)0mmmAS z0u>x&|L5+S=vG710}r=^kKL$-ilt0dNJ{@uS-q)z10w4MkTV}a(y6jBCs&x>mh8xPM>b0lijM%8l_va zmgC+z`|8+UCCx2voS23=%WR*X)_`9!zYXMG+0 zq_hR+$9oKSjLx1@jiEbU)h4eOkFy$#MXfB%BkEX| z^bliS^fJ8UN4}C{Kl0ntn8KW&B|94f74ozisc*|nmwC5DJfvWNwA@rybgM1*D(SXE zFR!zR93m(iuhvuV(u~tCYuvHIo>IPGsmKJ%-Kx^CilUh=O0=({7mE9I*?ynvI1(hX z&Bl0mjkRWr3!9pt={RW?X+PIDqByxL?L?1f2 zS4cBwHDPbb<|o;puM*4DCN`m&nOS>096ywLM`RbL#4>x0RFP*er~>t_$O`6 z+(=UMWT@Br6R}+lp4X)#fy=e=6UEPY4s~uC^QGbA_qrd`7?)N)AA2u!zu(;8o4LI4 zBk!{Evs6SM-OrG4$<(*SI?FP}M4n-b*|NgK0K?`N{*fb4 zzcEE9%-PZK`%W#|Gx+A2Wdm2eSg&Vw&U^flWZ`Joh+8^6UBz%g361NHXzfOz)0x4PDhyVZp literal 0 HcmV?d00001 diff --git a/21-VBA/SigningYourVBAProject.cs b/21-VBA/SigningYourVBAProject.cs new file mode 100644 index 0000000..8cf1ad0 --- /dev/null +++ b/21-VBA/SigningYourVBAProject.cs @@ -0,0 +1,48 @@ +using OfficeOpenXml; +using OfficeOpenXml.VBA; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + class SigningYourVBAProject + { + /// + /// Opens the Battleships sample and sign it with the certificate from the pfx file. + /// + public static void Run() + { + //Load our test certificate from the pfx file. + //In a real production environment, make to store your certificate in a secure way. + var cert = new X509Certificate2(FileUtil.GetRootDirectory().FullName + "\\21-VBA\\SampleCertificate.pfx", "EPPlus"); + + //Open the workbook created in the previous sample. + using (var p = new ExcelPackage(FileUtil.GetFileInfo("21.3-CreateABattleShipsGameVba.xlsm"))) + { + var signature = p.Workbook.VbaProject.Signature; + + //The only thing you need to do to sign your project is to set the signatures 'Certificate' property with your code-signing certificate. + //The certificate must have access to the private key to sign the project. + signature.Certificate = cert; + + //If the file is unsigned, EPPlus will by default create all three signatures - Legacy, Agile and V3. + //You can use the property 'CreateSignatureOnSave' to decide which signature version you want to create on saving the workbook. + //For example 'signature.LegacySignature.CreateSignatureOnSave = false' to remove the legacy signature. + + //You can also set the hash algorithm for each signature version. + //The Excel and EPPlus default is MD5 for the legacy signature and SHA1 for the Agile and V3 signature. + //We want to change it to SHA256 to get better and more modern hash algorithm. + signature.LegacySignature.HashAlgorithm = VbaSignatureHashAlgorithm.SHA256; + signature.AgileSignature.HashAlgorithm = VbaSignatureHashAlgorithm.SHA256; + signature.V3Signature.HashAlgorithm = VbaSignatureHashAlgorithm.SHA256; + + p.SaveAs(FileUtil.GetFileInfo("21.4-Signed-CreateABattleShipsGameVba.xlsm")); + } + } + + } +} diff --git a/33-ToCollection/Readme.md b/33-ToCollection/Readme.md new file mode 100644 index 0000000..65f8611 --- /dev/null +++ b/33-ToCollection/Readme.md @@ -0,0 +1,6 @@ +# 33 - ToCollection and ToCollectionWithMappings +This samples demonstrates Export ranges and tables into an IEnumerable<T> where T is a class type. +### [ToCollectionSample.cs](ToCollectionSample.cs) +### [ToCollectionClasses.cs](ToCollectionClasses.cs) (sample data) +--- +[Back to overview](/Readme.md) diff --git a/33-ToCollection/ToCollectionClasses.cs b/33-ToCollection/ToCollectionClasses.cs new file mode 100644 index 0000000..7914624 --- /dev/null +++ b/33-ToCollection/ToCollectionClasses.cs @@ -0,0 +1,90 @@ +using OfficeOpenXml.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public class ToCollectionSamplePerson + { + public ToCollectionSamplePerson() + { + + } + + public ToCollectionSamplePerson(string firstName, string lastName, int height, DateTime birthDate) + { + FirstName = firstName; + LastName = lastName; + Height = height; + BirthDate = birthDate; + } + + public string FirstName { get; set; } + + public string LastName { get; set; } + + public int Height { get; set; } + + public DateTime BirthDate { get; set; } + } + + public class ToCollectionSamplePersonAttr + { + public ToCollectionSamplePersonAttr() + { + + } + + public ToCollectionSamplePersonAttr(string firstName, string lastName, int height, DateTime birthDate) + { + FirstName = firstName; + LastName = lastName; + Height = height; + BirthDate = birthDate; + } + + [DisplayName("The persons first name")] + public string FirstName { get; set; } + + [Description("The persons last name")] + public string LastName { get; set; } + + [EpplusTableColumn(Header ="Height of the person")] + public int Height { get; set; } + + public DateTime BirthDate { get; set; } + } + + public static class ToCollectionSampleData + { + public static IEnumerable Persons + { + get + { + return new List + { + new ToCollectionSamplePerson("John", "Doe", 176, new DateTime(1978, 3, 15)), + new ToCollectionSamplePerson("Sven", "Svensson", 183, new DateTime(1995, 11, 3)), + new ToCollectionSamplePerson("Jane", "Doe", 168, new DateTime(1989, 2, 26)) + }; + } + } + + public static IEnumerable PersonsWithAttributes + { + get + { + return new List + { + new ToCollectionSamplePersonAttr("John", "Doe", 176, new DateTime(1978, 3, 15)), + new ToCollectionSamplePersonAttr("Sven", "Svensson", 183, new DateTime(1995, 11, 3)), + new ToCollectionSamplePersonAttr("Jane", "Doe", 168, new DateTime(1989, 2, 26)) + }; + } + } + } +} diff --git a/33-ToCollection/ToCollectionSample.cs b/33-ToCollection/ToCollectionSample.cs new file mode 100644 index 0000000..bd860d7 --- /dev/null +++ b/33-ToCollection/ToCollectionSample.cs @@ -0,0 +1,140 @@ +using OfficeOpenXml; +using OfficeOpenXml.Table; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EPPlusSamples +{ + public static class ToCollectionSample + { + public static void Run() + { + using(var package = new ExcelPackage()) + { + var ws = package.Workbook.Worksheets.Add("Persons"); + // Load the sample data into the worksheet + var range = ws.Cells["A1"].LoadFromCollection(ToCollectionSampleData.Persons, options => + { + options.PrintHeaders = true; + options.TableStyle = TableStyles.Dark1; + }); + + /********************************************************** + * ToCollection. Automaps cell data to class instance * + **********************************************************/ + + Console.WriteLine("******* Sample 33 - ToCollection ********\n"); + + // export the data loaded into the worksheet above to a collection + var exportedPersons = range.ToCollection(); + + foreach(var person in exportedPersons) + { + Console.WriteLine("***************************"); + Console.WriteLine($"Name: {person.FirstName} {person.LastName}"); + Console.WriteLine($"Height: {person.Height} cm"); + Console.WriteLine($"Birthdate: {person.BirthDate.ToShortDateString()}"); + } + + Console.WriteLine(); + + /********************************************************** + * ToCollectionWithMappings. Use this method to manually * + * map all or just some of the cells to your class. * + **********************************************************/ + + Console.WriteLine("******* Sample 33 - ToCollectionWithMappings ********\n"); + + var exportedPersons2 = ws.Cells["A1:D4"].ToCollectionWithMappings( + row => + { + // this runs once per row in the range + + // Create an instance of the exported class + var person = new ToCollectionSamplePerson(); + + // If some of the cells can be automapped, start by automapping the row data to the class + row.Automap(person); + + // Note that you can only use column names as below + // if options.HeaderRow is set to the 0-based row index + // of the header row. + person.FirstName = row.GetValue("FirstName"); + + // get value by the 0-based column index + person.Height = row.GetValue(2); + + // return the class instance + return person; + }, + options => options.HeaderRow = 0); + + foreach (var person in exportedPersons2) + { + Console.WriteLine("***************************"); + Console.WriteLine($"Name: {person.FirstName} {person.LastName}"); + Console.WriteLine($"Height: {person.Height} cm"); + Console.WriteLine($"Birthdate: {person.BirthDate.ToShortDateString()}"); + } + + Console.WriteLine(); + + /********************************************************** + * ToCollection. Using property attributes for mappings, * + * see the ToCollectionSamplePersonAttr class * + **********************************************************/ + + // Load the sample data into a new worksheet + var ws2 = package.Workbook.Worksheets.Add("Ws2"); + var range2 = ws2.Cells["A1"].LoadFromCollection(ToCollectionSampleData.PersonsWithAttributes, options => + { + options.PrintHeaders = true; + options.TableStyle = TableStyles.Dark1; + }); + + Console.WriteLine("******* Sample 33 - ToCollection using attributes ********\n"); + + // export the data loaded into the worksheet above to a collection + var exportedPersons3 = range2.ToCollection(); + + foreach (var person in exportedPersons3) + { + Console.WriteLine("***************************"); + Console.WriteLine($"Name: {person.FirstName} {person.LastName}"); + Console.WriteLine($"Height: {person.Height} cm"); + Console.WriteLine($"Birthdate: {person.BirthDate.ToShortDateString()}"); + } + + Console.WriteLine(); + + /********************************************************** + * ToCollection from a table * + **********************************************************/ + Console.WriteLine("******* Sample 33 - ToCollection from a table ********\n"); + // Load the sample data a new worksheet + var ws3 = package.Workbook.Worksheets.Add("Ws3"); + var tableRange = ws3.Cells["A1"].LoadFromCollection(ToCollectionSampleData.Persons, options => + { + options.PrintHeaders = true; + options.TableStyle = TableStyles.Dark1; + }); + var table = ws3.Tables.GetFromRange(tableRange); + // export the data loaded into the worksheet above to a collection + var exportedPersons4 = table.ToCollection(); + + foreach (var person in exportedPersons4) + { + Console.WriteLine("***************************"); + Console.WriteLine($"Name: {person.FirstName} {person.LastName}"); + Console.WriteLine($"Height: {person.Height} cm"); + Console.WriteLine($"Birthdate: {person.BirthDate.ToShortDateString()}"); + } + + Console.WriteLine(); + } + } + } +} diff --git a/App.config b/App.config index feed071..8701204 100644 --- a/App.config +++ b/App.config @@ -13,15 +13,23 @@ + + + + + - - - - - + + + + + + + + \ No newline at end of file diff --git a/EPPlus.Sample.NET.csproj b/EPPlus.Sample.NET.csproj index a65dd61..1196383 100644 --- a/EPPlus.Sample.NET.csproj +++ b/EPPlus.Sample.NET.csproj @@ -1,6 +1,6 @@  - + Debug @@ -37,44 +37,57 @@ - packages\EntityFramework.6.3.0\lib\net45\EntityFramework.dll + packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll - packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll + packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll - - packages\EPPlus.6.0.3\lib\net452\EPPlus.dll + + packages\EPPlus.6.1.0\lib\net462\EPPlus.dll - - packages\EPPlus.Interfaces.6.0.0\lib\net452\EPPlus.Interfaces.dll + + packages\EPPlus.Interfaces.6.1.0\lib\net452\EPPlus.Interfaces.dll - - packages\EPPlus.System.Drawing.6.0.0\lib\net452\EPPlus.System.Drawing.dll + + packages\EPPlus.System.Drawing.6.1.0\lib\net462\EPPlus.System.Drawing.dll - - packages\Microsoft.IO.RecyclableMemoryStream.1.4.1\lib\net46\Microsoft.IO.RecyclableMemoryStream.dll + + packages\Microsoft.IO.RecyclableMemoryStream.2.2.1\lib\net462\Microsoft.IO.RecyclableMemoryStream.dll - - packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + packages\System.ComponentModel.Annotations.4.7.0\lib\net461\System.ComponentModel.Annotations.dll - - packages\System.Data.SQLite.Core.1.0.112.0\lib\net46\System.Data.SQLite.dll + + packages\Stub.System.Data.SQLite.Core.NetFramework.1.0.116.0\lib\net46\System.Data.SQLite.dll - - packages\System.Data.SQLite.EF6.1.0.112.0\lib\net46\System.Data.SQLite.EF6.dll + + packages\System.Data.SQLite.EF6.1.0.116.0\lib\net46\System.Data.SQLite.EF6.dll - - packages\System.Data.SQLite.Linq.1.0.112.0\lib\net46\System.Data.SQLite.Linq.dll + + packages\System.Data.SQLite.Linq.1.0.116.0\lib\net46\System.Data.SQLite.Linq.dll + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + @@ -125,6 +138,7 @@ + @@ -140,6 +154,8 @@ + + @@ -172,6 +188,7 @@ + @@ -185,6 +202,7 @@ + PreserveNewest @@ -211,10 +229,10 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + - - + + \ No newline at end of file diff --git a/Readme.md b/Readme.md index 49c16d3..72ce103 100644 --- a/Readme.md +++ b/Readme.md @@ -25,7 +25,7 @@ The solution can be opened in Visual Studio for Windows. |17|[FX report](/17-FXReportFromDatabase/)|Exchange rates report with data from a SQL database. Demonstrates some of the chart capabilities of EPPlus| |18|[Pivot tables](/18-PivotTables/)|Demonstrates the Pivot table functionality of EPPlus.| |19|[Encryption and protection](/19-EncryptionAndProtection/)|This sample produces a quiz, where the template workbook is encrypted and password protected.| -|20|[Create filesystem report](/20-CreateFileSystemReport/)|Demonstrates usage of styling, printer settings, rich text, pie-, doughnut- and bar-charts, freeze panes| +|20|[Create filesystem report](/20-CreateFileSystemReport/)|Demonstrates usage of styling, printer settings, rich text, pie-, doughnut- and bar-charts, freeze panes and row/column outlines| |21|[VBA - Visual Basic for Applications](/21-VBA/)|Demonstrates EPPlus support for VBA, includes a battleship game| |22|[Ignore errors](/22-IgnoreErrors/)|Various samples on how to ignore error on cells.| |23|[Comments](/23-Comments/)|Sample showing how to add notes and threaded comments.| @@ -38,6 +38,7 @@ The solution can be opened in Visual Studio for Windows. |30|[Sorting Ranges](/30-WorkingWithRanges)|Shows how to work with the Sort method for ranges and tables |31|[Html Export](/31-HtmlExport)|Shows how to export tables and ranges to HTML |32|[Json Export](/32-JsonExport)|Shows how to export tables and ranges to JSON +|33|[ToCollection](/33-ToCollection)|Shows how to export data from worksheets and tables into an IEnumerable<T> where T is a class. ### Output files The samples above produces some workbooks - the name of each workbook indicates which sample that generated it. These workbooks are located in a subdirectory - named "SampleApp" - to the output directory of the sample project. diff --git a/Sample_Main.cs b/Sample_Main.cs index ad68a18..0b5f2ae 100644 --- a/Sample_Main.cs +++ b/Sample_Main.cs @@ -188,9 +188,10 @@ await ChartsAndThemesSample.RunAsync(connectionStr, Console.WriteLine("Sample 20 created:", output); Console.WriteLine(); - //Sample 21 - Shows how to work with macro-enabled workbooks(VBA). + //Sample 21 - Shows how to work with macro-enabled workbooks(VBA) and how to sign the code with a certificate. Console.WriteLine("Running sample 21-VBA"); WorkingWithVbaSample.Run(); + SigningYourVBAProject.Run(); Console.WriteLine("Sample 21 created {0}", FileUtil.OutputDir.Name); Console.WriteLine(); @@ -265,6 +266,14 @@ await ChartsAndThemesSample.RunAsync(connectionStr, await JsonExportSample.RunAsync(); Console.WriteLine("Sample 32 finished."); Console.WriteLine(); + + // Sample 33 - ToCollection and ToCollectionWithMappings + // This sample shows how to export data from a worksheet + // to a IEnumerable where T is a class. + Console.WriteLine("Running sample 33 - ToCollection and ToCollectionWithMappings"); + ToCollectionSample.Run(); + Console.WriteLine("Sample 33 finished."); + Console.WriteLine(); } catch (Exception ex) { diff --git a/packages.config b/packages.config index 66597d5..1998b06 100644 --- a/packages.config +++ b/packages.config @@ -1,14 +1,19 @@  - - - - - - + + + + + + + + - - - - + + + + + + + \ No newline at end of file From 06770be9b10ed2ac7cd55a8e6bc044f47069a146 Mon Sep 17 00:00:00 2001 From: swmal <897655+swmal@users.noreply.github.com> Date: Wed, 14 Jun 2023 15:07:48 +0200 Subject: [PATCH 17/18] Added a clarifying comment to sample 5 --- 05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs b/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs index b9f2a87..7dcb0e0 100644 --- a/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs +++ b/05-ImportAndExportCsvFiles/ImportAndExportCsvFilesSample.cs @@ -53,6 +53,11 @@ private static async Task ExportTableAsync(ExcelPackage package) { var ws = package.Workbook.Worksheets[1]; var tbl = ws.Tables[0]; + + // Note that we are changing Delimiter to semi-colon in this example. + // This is just to show that you can use any character as delimiter in your exported + // csv-data. The default delimiter is comma (','). + // The Culture property is for how numbers, dates, etc are formatted in the exported csv-data. var format = new ExcelOutputTextFormat { Delimiter = ';', From 1ec6a77b8c88eede87c3a9bc60d5a355e3bd81f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4llman?= Date: Thu, 26 Oct 2023 16:03:34 +0200 Subject: [PATCH 18/18] Update Readme.md --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 72ce103..63c3184 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,5 @@ -# EPPlus samples +## This sample project is for EPPlus 6, a newer sample for EPPlus 7 is available here... [C#](https://github.com/EPPlusSoftware/EPPlus.Samples.CSharp) or [VB](https://github.com/EPPlusSoftware/EPPlus.Samples.VB) +## EPPlus samples ### EPPlus samples for .NET Framework