我正在将Excel Interop数据透视表代码移植到EPPlus。我在生成计算字段值时处于困境。在Excel Interop中我可以这样做:
pvt.AddDataField(pvt.PivotFields("TotalQty"), "Total Packages", XlConsolidationFunction.xlSum).NumberFormat = "###,##0";
pvt.AddDataField(pvt.PivotFields("TotalPrice"), "Total Purchases", XlConsolidationFunction.xlSum).NumberFormat = "$#,##0.00";
PivotField avg = pvt.CalculatedFields().Add("Average Price", "=TotalPrice/TotalQty", true);
avg.Orientation = XlPivotFieldOrientation.xlDataField;
avg.NumberFormat = "$###0.00";
这是"平均价格"数据透视表上的值显示TotalPrice的值除以TotalQty。
但是如何在EPPlus中做到这一点?我可以制作"普通香草"像这样的数据字段:
var totQtyField = pivotTable.Fields["TotalQty"];
pivotTable.DataFields.Add(totQtyField);
var totPriceField = pivotTable.Fields["TotalPrice"];
pivotTable.DataFields.Add(totPriceField);
......但是在计算价值时,我感到困惑。我的出发点是一个类似的总和的在线示例:
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]).Function =
OfficeOpenXml.Table.PivotTable.DataFieldFunctions.Sum();
所以我尝试了以下内容,但没有一个是正确的:
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]).Function =
OfficeOpenXml.Table.PivotTable.DataFieldFunctions.Average(totPriceField, totQtyField);
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]).Function = "TotalPrice/TotalQty";
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]) = "TotalPrice/TotalQty";
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]) = totPriceField / totQtyField;
pivotTable.DataFields.Add(pivotTable.Fields["AvgPrice"]).Function =
OfficeOpenXml.Table.PivotTable.
DataFieldFunctions.Product(totPriceField/totQtyField);
这些违规都没有编译。我需要做出哪些调整,或者我需要采取什么样的全新方法?
我可以计算出数值并将它们放在数据表中并以这种方式引用它;但这真的是唯一/最好的方法吗?
我这样做了(将val直接添加到包含数据透视表的源数据的工作表中):
var avgCell = rawDataWorksheet.Cells[_lastRowAddedRawData + 1, 9];
if ((TotalPrice < 0.0M) || (Quantity < 1))
{
avgCell.Value = 0.0;
}
else
{
avgCell.Value = TotalPrice / Quantity;
}
var prcntgCell = rawDataWorksheet.Cells[_lastRowAddedRawData + 1, 10];
if ((TotalPrice < 0.0M) || (MonthYear == String.Empty))
{
prcntgCell.Value = 0.0;
}
else
{
prcntgCell.Value = GetPercentageOfItemForMonthYear(TotalPrice, MonthYear);
}
private double GetPercentageOfItemForMonthYear(decimal totPrice, strin
monthYear)
{
decimal totalForMonthYear = monthlySales[monthYear];
double prcntg = GetPercentageOfItem(totPrice, totalForMonthYear);
return prcntg;
}
private double GetPercentageOfItem(decimal portionOfTotal, decimal
grandTotal)
{
if ((portionOfTotal <= 0.0M) || (grandTotal <= 0.0M))
{
return 0.0;
}
if (portionOfTotal == grandTotal)
{
return 100.0;
}
double d = Convert.ToDouble(portionOfTotal)
/ Convert.ToDouble(grandTotal) * 100;
return Math.Round(d, 2);
}
...但仍然想知道在创建数据透视表时如何使用计算字段完成此操作。
答案 0 :(得分:3)
EPPlus目前不支持数据透视表中的计算字段。我使用了以下解决方法:
using System.Linq;
using System.Xml;
using OfficeOpenXml.Table.PivotTable;
using ReflectionMagic;
public static ExcelPivotTableField AddCalculatedField(this ExcelPivotTable pivotTable, string calcFieldName, string formula)
{
var dynamicPivotTable = pivotTable.AsDynamic();
var maxIndex = pivotTable.Fields.Max(f => f.Index);
const string schemaMain = @"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
var cacheTopNode = dynamicPivotTable.CacheDefinition.CacheDefinitionXml.SelectSingleNode("//d:cacheFields", dynamicPivotTable.NameSpaceManager);
cacheTopNode.SetAttribute("count", (int.Parse(cacheTopNode.GetAttribute("count")) + 1).ToString());
var cacheFieldNode = dynamicPivotTable.CacheDefinition.CacheDefinitionXml.CreateElement("cacheField", schemaMain);
cacheFieldNode.SetAttribute("name", calcFieldName);
cacheFieldNode.SetAttribute("databaseField", "0");
cacheFieldNode.SetAttribute("formula", formula);
cacheFieldNode.SetAttribute("numFmtId", "0");
cacheTopNode.AppendChild(cacheFieldNode);
var topNode = dynamicPivotTable.PivotTableXml.SelectSingleNode("//d:pivotFields", dynamicPivotTable.NameSpaceManager);
topNode.SetAttribute("count", (int.Parse(topNode.GetAttribute("count")) + 1).ToString());
XmlElement fieldNode = dynamicPivotTable.PivotTableXml.CreateElement("pivotField", schemaMain);
fieldNode.SetAttribute("compact", "0");
fieldNode.SetAttribute("outline", "0");
fieldNode.SetAttribute("showAll", "0");
fieldNode.SetAttribute("defaultSubtotal", "0");
topNode.AppendChild(fieldNode);
var excelPivotTableFieldType = typeof(ExcelPivotTableField).AsDynamicType();
var excelPivotTableField = excelPivotTableFieldType.New((XmlNamespaceManager)dynamicPivotTable.NameSpaceManager, fieldNode, (ExcelPivotTable)dynamicPivotTable, maxIndex + 1, maxIndex + 1);
excelPivotTableField.SetCacheFieldNode(cacheFieldNode);
dynamicPivotTable.Fields.AddInternal(excelPivotTableField);
return pivotTable.Fields.First(f => f.Name == calcFieldName);
}
使用示例:
var calc1 = pivotTable.AddCalculatedField("Calc1", "BCol*BCol");
var dataField = pivotTable.DataFields.Add(calc1);
dataField.Function = DataFieldFunctions.Sum;
dataField.Name = "Override Name";