对于笔者这样的数据分析工作者来说,对数据库有较深的掌握,当然少不了对SQL查询的深度使用,如果在编程的世界中,可以复用这样的能力,真的是一件多么令人高兴的事情。
在.Net的世界中,恰恰提供了这样的能力,用LINQ,仿佛回到了写SQL语句查询的环境中,对编辑中的使用的各种对象集合,在排序、筛选、去重等SQL语句常用的功能上,在LINQ的帮助下,一样可以对代码中的集合对象进行这些操作,代码量简洁无比。
所以在VBA的世界中,对某对象进行排序、筛选、去重等操作,在VSTO的世界中,使用LINQ来操作,将变得十分简单。
例如经常需要遍历单元格区域,肯定少不了For Each IF等代码,但使用了LINQ后,真心变得很简单,特别是操作一个多列的表单结构的数据时,前面提到笔者喜欢将其转换为DataTable,因为这样的数据结构就可以用上了LINQ。
除了前面提到的区域转DataTable的方法外,其实笔者还用到过LinqToExcel这个类库,同样也是非常好用,有兴趣的朋友们,可以搜索了解下,示例文件也是做得很丰富易懂。 具体地址为:https://github.com/paulyoder/LinqToExcel
在Excel上使用LINQ访问集合对象
简单演示下用过的一些小代码
获取当前数据区域中的非隐藏行的行号集合。
代码语言:javascript复制 public static int[] GetVisibleRowIndexs(Excel.Range srcDataRange)
{
int srcRangefirstRow = srcDataRange.Row;
int[] visibleRowIndexs = srcDataRange.Rows.Cast<Excel.Range>().Skip(1).Where(s => s.Height > 0).Select(t => t.Row - srcRangefirstRow).ToArray();
return visibleRowIndexs;
}
获取数据区域单元格,过滤隐藏、错误、空值等
代码语言:javascript复制 public static IEnumerable<Excel.Range> GetUsedDataValuesFromActiveSelection()
{
Excel.Range selRange = Common.ExcelApp.Selection as Excel.Range;
if (selRange != null)
{
//防止全选,和usedRange做一下交集处理
Excel.Range srcDataRange = Common.ExcelApp.Intersect(selRange, selRange.Worksheet.UsedRange);
//只要可见单元格,且只要有值的单元格
return srcDataRange.SpecialCells(Excel.XlCellType.xlCellTypeVisible).Cells.Cast<Excel.Range>()
.Where(s => s.Value2 != null);
}
else
{
return Enumerable.Empty<Excel.Range>();
}
}
将Excel里的集合对象转换为LINQ可以调用的方法,只需使用一下Cast<>转换一下即可,十分方便。 例如转换单元格就是Range.Cells.Cast(),转换工作表,就是Workbooks.WorkSheets.Cast()。
结语
LINQ真的是.Net语言一个非常好用的技术,可以让代码写起来无比流畅,非常值得学习掌握,当然VBA转到VSTO开发的群体,也优先学习这个技术,让自己的代码写出来,更加.Net化,而不是简单的只是语法转换。