创建高级过滤器

Create advanced filter

我正在尝试从 C# 在 Excel 中创建一个高级过滤器,以将唯一数据从一个 sheet 复制到另一个,至少我在 Excel 中得到它,如果我使用像这样的互操作:

   Excel.Range rang = sheet2.get_Range("A2");  
   Excel.Range oRng = sheet.get_Range("I2", "I" + (lst.Count + 1));


    oRng.AdvancedFilter(Excel.XlFilterAction.xlFilterCopy, CriteriaRange: Type.Missing,
                        CopyToRange: rang, Unique: true);

工作正常,但我正在使用 EPPlus 完成我的所有应用程序,如果我可以在没有 Interop 的情况下做同样的事情会更好。

那么,有可能吗?

由于高级过滤器是一项 excel 功能,您需要完整的 Excel DOM 才能访问它。 Epplus 没有那个 - 它只是生成 XML 以馈送到 excel,然后它将应用它的 "interpretation",可以这么说。

但是由于您拥有 .NET 的强大功能,您可以使用 linq 相当轻松地通过查询单元格存储并使用 .distinct() 获取唯一列表来完成同样的事情.唯一的问题是您必须创建自己的 IEquitableComparer。这将做到:

[TestMethod]
public void Distinct_Filter_Test()
{
    //Throw in some data
    var datatable = new DataTable("tblData");
    datatable.Columns.AddRange(new[]
    {
        new DataColumn("Col1", typeof (int)), new DataColumn("Col2", typeof (string))
    });

    var rnd = new Random();
    for (var i = 0; i < 10; i++)
    {
        var row = datatable.NewRow();
        row[0] = rnd.Next(1, 3) ;row[1] = i%2 == 0 ? "even": "odd";
        datatable.Rows.Add(row);
    }

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

    using (var pck = new ExcelPackage(fi))
    {
        //Load the random data
        var workbook = pck.Workbook;
        var worksheet = workbook.Worksheets.Add("data");
        worksheet.Cells.LoadFromDataTable(datatable, true);

        //Cells only contains references to cells with actual data
        var rows = worksheet.Cells
            .GroupBy(cell => cell.Start.Row)
            .Skip(1) //Exclude header
            .Select(cg => cg.Select(c => c.Value).ToArray())
            .Distinct(new ArrayComparer())
            .ToArray();

        //Copy the data to the new sheet
        var worksheet2 = workbook.Worksheets.Add("Distinct");
        worksheet2.Cells.LoadFromArrays(rows);

        pck.Save();
    }

}


public class ArrayComparer: IEqualityComparer<object[]>
{
    public bool Equals(object[] x, object[] y)
    {
        return !x.Where((o, i) => !o.Equals(y[i])).Any();
    }

    public int GetHashCode(object[] obj)
    {
        //Based on Jon Skeet Stack Overflow Post
        unchecked
        {
            return obj.Aggregate((int) 2166136261, (acc, next) => acc*16777619 ^ next.GetHashCode());
        }
    }
}