2014-09-12 55 views

回答

9

这是一个简单的例子。请注意,EEPlus无法进行页面过滤,所以您将不得不使用VBA,Excel Interop或XML操作(我在下面使用了XML)。你可以把这个代码放到EPPlus源码下载,简单的测试的单元测试:

const string FORMATCURRENCY = "#,###;[Red](#,###)"; 

var file = new FileInfo(@"c:\temp\temp.xlsx"); 
if (file.Exists) 
    file.Delete(); 

var pck = new ExcelPackage(file); 
var workbook = pck.Workbook; 
var worksheet = workbook.Worksheets.Add("newsheet"); 

//The data 
worksheet.Cells["A20"].Value = "Col1"; 
worksheet.Cells["A21"].Value = "sdf"; 
worksheet.Cells["A22"].Value = "wer"; 
worksheet.Cells["A23"].Value = "ghgh"; 
worksheet.Cells["A24"].Value = "sdf"; 
worksheet.Cells["A25"].Value = "wer"; 
worksheet.Cells["A26"].Value = "ghgh"; 
worksheet.Cells["A27"].Value = "sdf"; 
worksheet.Cells["A28"].Value = "wer"; 
worksheet.Cells["A29"].Value = "ghgh"; 

worksheet.Cells["B20"].Value = "Col2"; 
worksheet.Cells["B21"].Value = "Group A"; 
worksheet.Cells["B22"].Value = "Group B"; 
worksheet.Cells["B23"].Value = "Group A"; 
worksheet.Cells["B24"].Value = "Group C"; 
worksheet.Cells["B25"].Value = "Group A"; 
worksheet.Cells["B26"].Value = "Group B"; 
worksheet.Cells["B27"].Value = "Group C"; 
worksheet.Cells["B28"].Value = "Group C"; 
worksheet.Cells["B29"].Value = "Group A"; 

worksheet.Cells["C20"].Value = "Col3"; 
worksheet.Cells["C21"].Value = 453; 
worksheet.Cells["C22"].Value = 634; 
worksheet.Cells["C23"].Value = 274; 
worksheet.Cells["C24"].Value = 453; 
worksheet.Cells["C25"].Value = 634; 
worksheet.Cells["C26"].Value = 274; 
worksheet.Cells["C27"].Value = 453; 
worksheet.Cells["C28"].Value = 634; 
worksheet.Cells["C29"].Value = 274; 

worksheet.Cells["D20"].Value = "Col4"; 
worksheet.Cells["D21"].Value = 686468; 
worksheet.Cells["D22"].Value = 996440; 
worksheet.Cells["D23"].Value = 185780; 
worksheet.Cells["D24"].Value = 686468; 
worksheet.Cells["D25"].Value = 996440; 
worksheet.Cells["D26"].Value = 185780; 
worksheet.Cells["D27"].Value = 686468; 
worksheet.Cells["D28"].Value = 996440; 
worksheet.Cells["D29"].Value = 185780; 

//The pivot table 
var pivotTable = worksheet.PivotTables.Add(worksheet.Cells["A4"], worksheet.Cells["A20:D29"], "test"); 

//The label row field 
pivotTable.RowFields.Add(pivotTable.Fields["Col1"]); 
pivotTable.DataOnRows = false; 

//The data fields 
var field = pivotTable.DataFields.Add(pivotTable.Fields["Col3"]); 
field.Name = "Sum of Col2"; 
field.Function = DataFieldFunctions.Sum; 
field.Format = FORMATCURRENCY; 

field = pivotTable.DataFields.Add(pivotTable.Fields["Col4"]); 
field.Name = "Sum of Col3"; 
field.Function = DataFieldFunctions.Sum; 
field.Format = FORMATCURRENCY; 

//The page field 
pivotTable.PageFields.Add(pivotTable.Fields["Col2"]); 
var xdCacheDefinition = pivotTable.CacheDefinition.CacheDefinitionXml; 
var xeCacheFields = xdCacheDefinition.FirstChild["cacheFields"]; 
if (xeCacheFields == null) 
    return; 

//To filter, add items to the Cache Definition via XML 
var count = 0; 
var assetfieldidx = -1; 

foreach (XmlElement cField in xeCacheFields) 
{ 
    var att = cField.Attributes["name"]; 
    if (att != null && att.Value == "Col2") 
    { 
     assetfieldidx = count; 

     var sharedItems = cField.GetElementsByTagName("sharedItems")[0] as XmlElement; 
     if(sharedItems == null) 
      continue; 

     //set the collection attributes 
     sharedItems.RemoveAllAttributes(); 
     att = xdCacheDefinition.CreateAttribute("count"); 
     att.Value = "3"; 
     sharedItems.Attributes.Append(att); 

     //create and add the item 
     var item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI); 
     att = xdCacheDefinition.CreateAttribute("v"); 
     att.Value = "Group A"; 
     item.Attributes.Append(att); 
     sharedItems.AppendChild(item); 

     item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI); 
     att = xdCacheDefinition.CreateAttribute("v"); 
     att.Value = "Group B"; 
     item.Attributes.Append(att); 
     sharedItems.AppendChild(item); 

     item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI); 
     att = xdCacheDefinition.CreateAttribute("v"); 
     att.Value = "Group C"; 
     item.Attributes.Append(att); 
     sharedItems.AppendChild(item); 

     break; 
    } 

    count++; 
} 

//Now go back to the main pivot table xml and add the cross references to complete filtering 
var xdPivotTable = pivotTable.PivotTableXml; 
var xdPivotFields = xdPivotTable.FirstChild["pivotFields"]; 
if (xdPivotFields == null) 
    return; 

count = 0; 
foreach (XmlElement pField in xdPivotFields) 
{ 
    //Find the asset type field 
    if (count == assetfieldidx) 
    { 
     var att = xdPivotTable.CreateAttribute("multipleItemSelectionAllowed"); 
     att.Value = "1"; 
     pField.Attributes.Append(att); 

     var items = pField.GetElementsByTagName("items")[0] as XmlElement; 
     items.RemoveAll(); 

     att = xdPivotTable.CreateAttribute("count"); 
     att.Value = "4"; 
     items.Attributes.Append(att); 
     pField.AppendChild(items); 

     //Add the classes to the fields item collection 
     for (var i = 0; i < 3; i++) 
     { 
      var item = xdPivotTable.CreateElement("item", items.NamespaceURI); 
      att = xdPivotTable.CreateAttribute("x"); 
      att.Value = i.ToString(CultureInfo.InvariantCulture); 
      item.Attributes.Append(att); 

      //Turn of the Cash class in the fielder 
      if (i == 1) 
      { 
       att = xdPivotTable.CreateAttribute("h"); 
       att.Value = "1"; 
       item.Attributes.Append(att); 
      } 

      items.AppendChild(item); 

     } 

     //Add the default 
     var defaultitem = xdPivotTable.CreateElement("item", items.NamespaceURI); 
     att = xdPivotTable.CreateAttribute("t"); 
     att.Value = "default"; 
     defaultitem.Attributes.Append(att); 
     items.AppendChild(defaultitem); 

     break; 
    } 
    count++; 
} 

pck.Save(); 

对不起,所有的编辑,但我一直在这一会儿,当我无意中发现了这个问题, 。我创建了一个只用于应用过滤器的扩展方法。给它一个字段名称(它假定有一个包含列名的标题行),你要应用的过滤器和包含数据的工作表,或者如果没有数据工作表被传入,它将只是数据透视表工作表。做了基本的测试,所以你应该QA:

public static bool FilterField(this ExcelPivotTable pivotTable, string pageFieldName, IEnumerable<object> filters, ExcelWorksheet dataWorksheet = null) 
{ 
    //set the worksheet 
    var ws = dataWorksheet ?? pivotTable.WorkSheet; 

    //Set the cache definitions and cache fields 
    var xdCacheDefinition = pivotTable.CacheDefinition.CacheDefinitionXml; 
    var xeCacheFields = xdCacheDefinition.FirstChild["cacheFields"]; 
    if (xeCacheFields == null) 
     return false; 

    //Go the field list in the definitions, note the field idx and valuesfor 
    var count = 0; 
    var fieldIndex = -1; 
    List<object> fieldValues = null; 

    foreach (XmlElement cField in xeCacheFields) 
    { 
     var att = cField.Attributes["name"]; 
     if (att != null && att.Value.Equals(pageFieldName, StringComparison.OrdinalIgnoreCase)) 
     { 
      //store the field data 
      fieldIndex = count; 
      var dataddress = new ExcelAddress(pivotTable.CacheDefinition.SourceRange.Address); 

      var valueHeader = ws 
       .Cells[dataddress.Start.Row, dataddress.Start.Column, dataddress.Start.Row, dataddress.End.Column] 
       .FirstOrDefault(cell => cell.Value.ToString().Equals(pageFieldName, StringComparison.OrdinalIgnoreCase)); 

      if (valueHeader == null) 
       return false; 

      //Get the range minus the header row 
      var valueObject = valueHeader.Offset(1, 0, dataddress.End.Row - dataddress.Start.Row, 1).Value; 
      var values = (object[,])valueObject; 

      fieldValues = values 
       .Cast<object>() 
       .Distinct() 
       .ToList(); 

      //kick back if the types are mixed 
      if (fieldValues.FirstOrDefault(v => v is string) != null && fieldValues.FirstOrDefault(v => !(v is string)) != null) 
       throw new NotImplementedException("Filter function does not (yet) support mixed parameter types"); 

      //fill in the shared items for the field 
      var sharedItems = cField.GetElementsByTagName("sharedItems")[0] as XmlElement; 
      if (sharedItems == null) 
       continue; 

      //Reset the collection attributes 
      sharedItems.RemoveAllAttributes(); 

      //Handle numerics - assume all or nothing 
      var isNumeric = fieldValues.FirstOrDefault(v => v is string) == null; 
      if (isNumeric) 
      { 
       att = xdCacheDefinition.CreateAttribute("containsSemiMixedTypes"); 
       att.Value = "0"; 
       sharedItems.Attributes.Append(att); 

       att = xdCacheDefinition.CreateAttribute("containsString"); 
       att.Value = "0"; 
       sharedItems.Attributes.Append(att); 

       att = xdCacheDefinition.CreateAttribute("containsNumber"); 
       att.Value = "1"; 
       sharedItems.Attributes.Append(att); 

       att = xdCacheDefinition.CreateAttribute("containsInteger"); 
       att.Value = fieldValues.Any(v => !(v is int || v is long)) ? "0" : "1"; 
       sharedItems.Attributes.Append(att); 
      } 

      //add the count 
      att = xdCacheDefinition.CreateAttribute("count"); 
      att.Value = fieldValues.Count.ToString(CultureInfo.InvariantCulture); 
      sharedItems.Attributes.Append(att); 

      //create and add the item 
      foreach (var fieldvalue in fieldValues) 
      { 
       var item = xdCacheDefinition.CreateElement(isNumeric ? "n" : "s", sharedItems.NamespaceURI); 
       att = xdCacheDefinition.CreateAttribute("v"); 
       att.Value = fieldvalue.ToString(); 
       item.Attributes.Append(att); 
       sharedItems.AppendChild(item); 
      } 

      break; 
     } 

     count++; 
    } 

    if (fieldIndex == -1 || fieldValues == null) 
     return false; 

    //Now go back to the main pivot table xml and add the cross references to complete filtering 
    var xdPivotTable = pivotTable.PivotTableXml; 
    var xdPivotFields = xdPivotTable.FirstChild["pivotFields"]; 
    if (xdPivotFields == null) 
     return false; 

    var filtervalues = filters.ToList(); 
    count = 0; 
    foreach (XmlElement pField in xdPivotFields) 
    { 
     //Find the asset type field 
     if (count == fieldIndex) 
     { 
      var att = xdPivotTable.CreateAttribute("multipleItemSelectionAllowed"); 
      att.Value = "1"; 
      pField.Attributes.Append(att); 

      var items = pField.GetElementsByTagName("items")[0] as XmlElement; 
      if (items == null) 
       return false; 

      items.RemoveAll(); 

      att = xdPivotTable.CreateAttribute("count"); 
      att.Value = (fieldValues.Count + 1).ToString(CultureInfo.InvariantCulture); 
      items.Attributes.Append(att); 
      pField.AppendChild(items); 

      //Add the classes to the fields item collection 
      for (var i = 0; i < fieldValues.Count; i++) 
      { 
       var item = xdPivotTable.CreateElement("item", items.NamespaceURI); 
       att = xdPivotTable.CreateAttribute("x"); 
       att.Value = i.ToString(CultureInfo.InvariantCulture); 
       item.Attributes.Append(att); 

       if (filtervalues.Contains(fieldValues[i])) 
       { 
        att = xdPivotTable.CreateAttribute("h"); 
        att.Value = "1"; 
        item.Attributes.Append(att); 
       } 

       items.AppendChild(item); 
      } 

      //Add the default 
      var defaultitem = xdPivotTable.CreateElement("item", items.NamespaceURI); 
      att = xdPivotTable.CreateAttribute("t"); 
      att.Value = "default"; 
      defaultitem.Attributes.Append(att); 
      items.AppendChild(defaultitem); 

      break; 
     } 
     count++; 
    } 

    return true; 

} 

要在上面的例子中使用它,你会做这样的事情:

pivotTable.FilterField("Col2", new List<string> { "Group B" }); 
+1

感谢厄尼,它帮助我很多.. – banny 2015-02-27 09:51:42

+0

FilterField的伟大工程! – Jabe 2016-04-20 06:27:56

相关问题