创建高级过滤器
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());
}
}
}
我正在尝试从 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());
}
}
}