本人为小白,此篇仅为记录自己初次接触C# VSTO写Excel插件遇到的一些问题。
一、遇到的问题
1.如何获取当前的Excel文件;
2.如何当前表格有多少行(不算解决);
3.如何获取鼠标选中的区域;
4.调试的时候如何才能打印出一些变量的值(未解决);
5.调试的时候Excel表对应的位置没有显示插件的界面;
6.插件发布之后的安装和卸载;
二、解决方法
1.获取当前的Excel文件
在写代码之前有两个集合是必须被引用的:
1 using Microsoft.Office.Tools.Ribbon; 2 using Excel = Microsoft.Office.Interop.Excel;
首先使用全局变量类Globals获取一个Excel应用的进程(具体关于Globals我也不是很了解,只知道它可以用在这里),其中的Globals.ThisAddIn指的就是当前正在编写的插件。
1 public Excel.Application app; 2 app = Globals.ThisAddIn.Application;
其次通过Excel.Application类型的变量app就可以获取当前的工作簿(就是现在打开的Excel文件)、当前的表格、当前的单元格
public Excel.Workbook wb; wb = app.ActiveWorkbook;//当前的工作簿 public Excel.Worksheet worksheet; worksheet = app.ActiveSheet;//当前的表格 public Excel.Range cell; cell = app.ActiveCell;//当前的单元格
而所谓的当前的表格指的就是Excel界面左下方被选中的sheet(如Sheet1),当前的单元格就是指被鼠标单击一次之后被绿框包围的单元格(如D2)。
打开Excel文件也就是工作簿,还可以使用文件路径打开(获得对象和上方ActiveWorkbook相同)。Open方法中第一个参数是文件路径,剩下是14个Type.Missing(这些参数具体只能查看官方文档)。
string fileName = app.ActiveWorkbook.FullName;//获得当前excle的绝对路径 Excel.Workbook w = app.Workbooks.Open(fileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
2.如何获得当前表格有多少行;
我采用的是遍历的方法,遍历第一列的所有行。每一行都判断这一行是否为null,如果不是就把行数加1,如果是null则调用IsOver函数判断该行下方是否有连续1000个空行,如果没有连续1000个空行就认为该表格还没有到最后一行的下一行,行数继续加1,而如果有连续的1000个空行则认为该表格已经到达了最后一行的下一行,到此整个表格的所有行都遍历了一遍,跳出死循环,活动行数rowCount;
这样的方法很明显不是最好的方法,它很局限,如果存在一个两行数据之间有1000多个空行的表格(这种情况应该很少吧),或者存在第一列没有任何数据或字符的表格,或者存在第一列最后一行的行数并不是最大行数的表格,那么我这个方法将会不在有效。因此我认为自己并没有解决这个问题。
如果有大佬知道正确的获取表格行数的方法,希望可以告诉我。
1 public int rowCount = 0;//数据的行数 2 public int count;//row的更改次数 3 4 if (count == 0)//rowCount只改变一次 5 { 6 while (true)//获取表格总行数 7 { 8 if (worksheet.Cells[i, 1].value == null && IsOver(i)) 9 break; 10 rowCount++; 11 i++; 12 } 13 count++; 14 } 15 16 17 public bool IsOver(int i)//是否连续有x个空格,是返回True 18 { 19 int c = 0;//代表连续的空格数量 20 int x = 1000;//最多有多少个连续的空格结束 21 while (c<x) 22 { 23 if (worksheet.Cells[i, 1].value != null) 24 return false; 25 c++; 26 i++; 27 } 28 return true; 29 }
3.如何获取鼠标选中的区域
先把我找到的解决办法的网址放在这里。https://stackoverflow.com/questions/2110327/excel-getting-the-selected-rows-back
由于我现在只需要获得一块鼠标选中的区域,不需要获得多个区域,所以下方的代码只能获得一块鼠标选中的区域(如果需要多个区域的话,希望上面这个网址的内容能对你有启发)。
Excel.Application 这个类中的Selection属性返回的是一个Excel.Range类型的值,就是鼠标选中的区域,暂且将他命名为range。无论你怎么框选单元格,range.row和rang.column永远都是框选区域左上角的的行数和列数,这远不能获得鼠标选中的整个区域,我们还需要左下角和右上角的行数和列数。range.Rows和range.Columns返回的是都是Excel.Range类型的值,它们所代表的的是鼠标框选区域的所有行和所有列,之后只需要使用foreach将它们遍历,记录遍历的最后一行的行号和最后一列的列号,就得到了左下角的行号和右上角的列号。到此获得了左上角,左下角和右上角三个单元格的行号和列号,也就是获得了整个鼠标所框选的区域。
1 private int firstR;//左上角的行数 2 private int firstC;//左上角的列数 3 private int rightC;//最右边的列数 4 private int downR;//最下边的行数 5 6 public void GetSelectArea()//获取鼠标选中的区域 7 { 8 Excel.Range range = app.Selection;//获取鼠标选中的区域 9 //List<int> rowNumber = new List<int>();//某区域所有的行数 10 //List<int> columnNumber = new List<int>();//某区域所有的列数 11 12 13 firstC = range.Column;//获取左上角的列数 14 firstR = range.Row;//获取左上角的行数 15 foreach (Excel.Range row in range.Rows) 16 { 17 downR = row.Row;//全部行遍历一遍之后就可以得到最后一行的行号 18 } 19 foreach (Excel.Range column in range.Columns) 20 { 21 rightC = column.Column;//同样,全部列遍历一遍之后就可以得到最好一列的列号 22 } 23 }
4.调试的时候如何才能打印出一些变量的值(未解决);
调试程序时如果我要查看某一个变量的值,我现在只会将变量的值打印在Excel的某个单元格中查看。
1 worksheet.Cells[1, 5].value = $"{rowCount}";
但我如何才能像平时一样在那个黑框框里打印出来,或者在Visual Studio里查看。如果有大佬知道方法,求指教。
5.调试的时候Excel表对应的位置没有显示插件的界面;
我遇到这个问题是因为我不小心把我这个项目从Excel开发工具-->COM加载项的列表中删除了(开发工具这个选项卡默认是没有开启的,需要自己开启)。
只要点击Visual Studio里生成-->清理解决方案(或者清理+你的项目名)之后,再次调试就可以了。
6.插件发布之后的安装和卸载;
假如写好插件之后想要把插件给别人用,只需要把这里改成Rlease,然后点击生成-->发布。
点击发布后修改发布的位置(点击下一步之后的其他修改我也不知道有什么作用)。点击完成即可。
将发布位置对应的这三个文件打包发给别人,让他运行里边的setup.exe就可以使用你写好的插件。
最后关于如何卸载自己的这个插件,我真是找了老半天。需要在Windows的应用管理里搜索你的项目名,也就是上3个文件中第二个文件的名字就可以卸载了。