如何在数据透视表EPPlus中应用条件格式

时间:2019-12-16 15:31:29

标签: c# excel pivot-table conditional-formatting epplus

我有一个ASP.NET Mvc应用程序,该应用程序使用EPPlus生成Excel报告。生成的工作簿中的工作表之一包含数据透视表。我想在数据透视表中应用条件格式来为值等于1的那些单元格上色。

以下代码用于创建数据透视表。

var dataRange = _objSheet.Cells[_objSheet.Dimension.Address.ToString()];
_objSheet = outputExcel.Workbook.Worksheets.Add("Pivot");
var ptTable = _objSheet.PivotTables.Add(_objSheet.Cells["A1"], dataRange, "PivotTable");
ptTable.GridDropZones = true;
ptTable.ApplyPatternFormats = true;
ptTable.Compact = false;
ptTable.CompactData = false;
ptTable.Indent = 0;
ptTable.RowGrandTotals = false;
ptTable.ColumnGrandTotals = false;
ptTable.ShowMemberPropertyTips = false;
ptTable.DataOnRows = false;
ptTable.UseAutoFormatting = false;

如何将条件格式应用于数据透视表范围?

1 个答案:

答案 0 :(得分:0)

可以这样做,但是需要对XML进行修改,因为epplus当前似乎不支持Pivot上的ConditionalFormatting属性:

https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.conditionalformatting.pivot?view=openxml-2.8.1

因此,如果您有数据透视表并添加格式,则可以设置标志,以便Excel将其与工作表中的数据透视表关联。例如:

[TestMethod]
public void Pivot_Table_Conditional_Format()
{
    //https://stackoverflow.com/questions/59359688/how-to-apply-conditional-formatting-in-pivot-table-epplus
    //Throw in some data
    var dt = new DataTable("tblData");
    dt.Columns.AddRange(new[]
    {
        new DataColumn("Group", typeof (string)),
        new DataColumn("MValue", typeof (int)),
        new DataColumn("Month", typeof (int)),
        new DataColumn("String", typeof (object))
    });

    var rnd = new Random();

    for (var i = 0; i < 100; i++)
    {
        var row = dt.NewRow();
        //This adds some randomness to the number of groups that will be created
        row[0] = $"Group {rnd.Next(1, 100)}";
        row[1] = i * rnd.Next(1, 100);

        //This adds randomness to the columns so not guaranteed to be all 12
        row[2] = rnd.Next(1, 12);
        row[3] = Path.GetRandomFileName();

        dt.Rows.Add(row);
    }

    //Create a test file
    var fi = new FileInfo(@"c:\temp\Pivot_Table_Conditional_Format.xlsx");
    if (fi.Exists)
        fi.Delete();

    using (var pck = new ExcelPackage(fi))
    {
        var wsData = pck.Workbook.Worksheets.Add("Data");
        wsData.Cells.LoadFromDataTable(dt, true);

        var wsPivot = pck.Workbook.Worksheets.Add("Pivot");

        var pivotTable1 = wsPivot.PivotTables.Add(
            wsPivot.Cells["A1"]
            , wsData.Cells[1, 1, wsData.Dimension.End.Row, wsData.Dimension.End.Column]
            , "DataPivot"
        );

        pivotTable1.DataFields.Add(pivotTable1.Fields["MValue"]);

        //Grouping will be by the "Group" column
        pivotTable1.RowFields.Add(pivotTable1.Fields["Group"]);

        //Columns will be months
        pivotTable1.ColumnFields.Add(pivotTable1.Fields["Month"]);

        //Set conditional formatting but have to determine the range in the pivot table
        var groups = dt
            .Rows
            .Cast<DataRow>()
            .Select(row => row["Group"])
            .Distinct()
            .ToList();

        var columns = dt
            .Rows
            .Cast<DataRow>()
            .Select(row => row["Month"])
            .Distinct()
            .ToList();

        var colOffset = pivotTable1.FirstDataCol;
        var groupOffset = pivotTable1.FirstDataRow + pivotTable1.FirstHeaderRow;

        var range = new ExcelAddress
        (
            pivotTable1.Address.Start.Row + groupOffset
            , pivotTable1.Address.Start.Column + colOffset
            , groups.Count + groupOffset
            , columns.Count + colOffset
        );

        var cond = wsPivot.ConditionalFormatting.AddGreaterThanOrEqual(range);
        cond.Formula = "100";
        cond.Style.Font.Color.Color = Color.Black;
        cond.Style.Fill.PatternType = ExcelFillStyle.Solid;
        cond.Style.Fill.BackgroundColor.Color = Color.Yellow;

        //Only way to set the pivot table as the target is with XML Hack
        var parent = cond.Node.ParentNode;
        var doc = parent.OwnerDocument;

        //Need an attribute "pivot" with a value of "1" (true)
        //https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.conditionalformatting.pivot?view=openxml-2.8.1
        var att = doc.CreateAttribute("pivot", doc.NamespaceURI);
        att.Value = "1";
        parent.Attributes.Append(att);

        pck.Save();
    }
}

这给出了这一点:

enter image description here