创建高级过滤器

时间:2015-10-28 17:56:11

标签: excel interop epplus

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

   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我可以做同样的事情会更好。

那么,有可能吗?

1 个答案:

答案 0 :(得分:1)

Since Advanced Filter is an excel function you need the full Excel DOM to access it. Epplus doesnt have that - it just generated the XML to feed to excel which will then apply its "interpretation", so to speak.

But since you have the power of .NET at your disposal, you can use linq fairly easily to do the same thing by querying the cell store and using .distinct() to get the unique list. The only wrinkle is you have to create your own IEquitableComparer. This will do it:

[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());
        }
    }
}