如何用C#制作Excel AddIn

摘要:
该报告采用EXCEL格式,每行和每列的布局已确定。向导将创建一个具有以下主体代码的类:publicpartialclassThisAddIn{privatepointThisAddIn_Startup{}privatepointThisAddIn_Shutdown{}}如果您不理解,可以猜到它。根据名称,您可以猜测Startup和Shutdown是在ThisAddIn_在Startup中加载和关闭插件时执行的事件。添加菜单的效果如下:特定代码编写为privatenoidThisAddIn_ Startup{#regionVSTOgeneratedcodethis.Application=Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.Wrap;#endregionthis.AddMenu();}办公室命令栏控制菜单顶部;办公室CommandBarControlmenuCreateMail=null;privatevoidAddMenu(){Office.CommandBarbar=this.Application.CommandBars.ActiveMenuBar;menuTop.Caption=“YiHuTools”;Office.Command BarPopupcommandBarPopupTmp=menuTop.ControlasOffice.CommandeBarPopup;menuCreateMail.Capton=“ImportData”;Office\CommandBarButtonButton Menu=menuCreateMailasOffice.CmmandBarButton;buttonMenu.Click+=newMicrosoft.Office.Core._CommandBarButtonEvents_ClickEventHandler;}这是一个提示。如果在AddMenu方法中定义了menuTop或menuCreateMail,则会导致在打开EXCEL后多次单击按钮事件,并且只执行一次。单击菜单“ImportData”,事件代码如下:void voidbutton menu_Click{//分析CSV文件并设置指定报告列的值需要很长的代码}。

AddIn 中文翻译为插件,有时候也叫Plug In,我的理解是,根据程序开发商提供的接口,让程序加载自定义的代码片段以完成某种功能。
这个需求源自于一个朋友的要求,他向我陈述了产生需求的原因。
朋友所在工厂的质量部每天需要检测大量的产品零部件,并且要把检测的数据制作成报表,这是QC测量员的日常工作。由于最近公司的订单增多,生产任务的增多也导致测量员每天需要检测大量的产品零件,产生大量的测量数据。QC测量员还需要把这些数据整理成规定格式的报表,提交给组长审核。订单的增多,会导致QC测量员工作量增加。他询问我,是否有办法可以减少QC测量员的工作量,提高工作效率。

从他的描述中看出,有两件工作是不断重复进行的:测量零件和制作报表。对于测量零件,我也没有办法去提高效率,除非规定只检测部分零件,而不是全部检测。在工厂规定必须全部检测的情况下,第一道工序很难优化。对于第二道工序,把测量的数据制作成报表。这一步似乎可以用程序来提高效率。因为要求制作的报表的格式是规定的,只需要把测量的结果数据导入到规定格式的报表中去,第二步就顺利完成。
报表采用EXCEL格式,每行每列的版面已经确定。只需要把指定的数据放到相应的列位置即可。如图
image

Item列是零件名称,Mean列是对应零件的测量数据。
测量机器导出的零件的数据格式支持常用的CSV,XML和TXT格式,导出的数据用EXCEL看起来是这样的
image

我选择把测量数据导出为csv格式,这种格式容易查看,也容易分析。如果选用XML格式,大多数据员工都看不懂,而且查看起来不方便。对于这类的平面结构(相对于层次结构)的数据,导出为CSV是首选。
接下来就是分析一下,如何快速的把测量数据制作成报表。

大部分EXCEL用户对公式比较熟悉,制作报表也相当专业和快速。我先尝试直接用公式解决。
这个需求用公式描述是,在指定的区域中找值,然后返回指定的值到相应的数据列中。
EXCEL的VLOOKUP函数可以达到我的目的。如下的解释:VLOOKUP(C1,A:B,2,) 这个公式,意思是要在A列到B列查找C1这个数据,并显示与其对应的B列的数据
但是有个问题,报表和测量数据是分别放在两在文件中的,而且测量数据是不允许被放到报表所在的文件中。用户需要先把测量数据添加到报表文件中,然后使用上面的公式,去找到匹配值,做完之后再把测量数据所在的worksheet删掉。如果有很多这样的报表要做,用户要反复的添加和删除worksheet,虽然可以解决问题,有点不完美,用户操作起来不方便。这个方案可以解决问题,但不完美,

尝试用VBA的方法,网上关于VBA的资料相当多。VBA就相当于程序的方式。我的思路是先读取测量数据文件,把它放到一个类似于字典的结构中(Hashtable,Dictionary),然后循环读取报表中需要数据的零件,取出它对应的测量数据并赋给相应的单元格。没研究过VBA,不知道怎样入手。用关键词“VBA如何读取一个文件”在网上找了搜索了很久也没有找到相关内容,这个方案不会编程实现,只好放弃。

考虑用VSTO。VS 2005/2008默认都会安装这个组件,它相当于托管版本的VBA。而且VSTO支持C#语言,可以用最熟悉的技术解决这个问题。在C#里面,读取一个文件相当容易,一个StreamReader就可以搞定读取文件的问题。
打开VS2008,新建一个Excel 2003的Workbook项目。
image 
向导会创建一个类,它的主体代码如下
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e){       }
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)   {       }
}
看不懂可以猜测,根据名字,猜测Startup和Shutdown是插件被加载和关闭时执行的事件
在ThisAddIn_Startup中,加载界面。
可以添加一个菜单,也可以添加一个工具按钮。添加菜单的效果如下
image
具体代码的写法是
private void ThisAddIn_Startup(object sender, System.EventArgs e)
       {
           #region VSTO generated code

           this.Application = (Excel.Application)Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.Wrap(typeof(Excel.Application), this.Application);

           #endregion         
           this.AddMenu();
       }
Office.CommandBarControl menuTop;
Office.CommandBarControl menuCreateMail = null;

private void AddMenu()
{
Office.CommandBar bar = this.Application.CommandBars.ActiveMenuBar;

menuTop.Caption = "YiHu Tools";

Office.CommandBarPopup commandBarPopupTmp = menuTop.Control as Office.CommandBarPopup;
menuCreateMail.Caption = "Import Data";

Office.CommandBarButton buttonMenu = menuCreateMail as Office.CommandBarButton;
buttonMenu.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(buttonMenu_Click);

}
这里有一个技巧。如果menuTop或menuCreateMail 在AddMenu方法中定义,会导致EXCEL打开后,多次点击按钮事件,它只执行一次。除非你重新启动EXCEL。
点击菜单“Import Data”的事件代码如下
void buttonMenu_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)

{

//分析CSV文件,设置指定报表列的值

}
代码比较长。首先是弹出对话框,选择要导入的包含测量数据的文件,分析并导入值。
导入值的代码涉及到操作EXCEL,代码如下
Excel.Worksheet sheet = (Excel.Worksheet)Application.ActiveWorkbook.ActiveSheet;                  
               int rowIndex = 10; int maxIndex = 300;
               for (rowIndex = 10; rowIndex < maxIndex;rowIndex++ )
               {
                   Excel.Range source = sheet.get_Range("A" + rowIndex, "A" + rowIndex);
                   Excel.Range target = sheet.get_Range("F" + rowIndex, "F" + rowIndex);
                   if (String.IsNullOrEmpty(source.Value2.ToString()))
                       continue;
                   else
                   {
                       string hashkey = source.Value2.ToString();
                       if (table.Contains(hashkey))
                           target.Value2 = table[hashkey].ToString();
                   }
               }
table的类型是Hashtable,它以零件名作键名,零件的测量数据为值。
读取文件的代码也有点技巧。我的机器是XP SP2英文版,EXCEL是2003的英文标准版。如果以COM Interop API读取数据文件,把数据文件当作EXCEL文件来读取,会经常出现乱码,如果是以文本文件的方式读取数据文件,则没有任何问题。这个问题我一直找不到原因。

下面说一下怎样部署这个插件 以下几个步骤是必须的,而且要以管理员身份才能执行以下步骤
1 在目标机器上,安装 .Net Framework 2.0 http://www.microsoft.com/downloads/details.aspx?FamilyID=0856EACB-4362-4B0D-8EDD-AAB15C5E04F5&displaylang=en

2 安装Office 2007 PIAs

http://www.microsoft.com/downloads/details.aspx?familyid=59DAEBAA-BED4-4282-A28C-B864D8BFA513&displaylang=en

3 安装 VSTO Runtime 2.0:

http://www.microsoft.com/downloads/details.aspx?FamilyId=4468D8CB-B43E-4B09-82F6-8BA3F7B5E935&displaylang=en#filelist

4 确保EXCEL 2003已经打上了SP2补丁,否则请安装SP2补丁
image 
5  编译安装项目,并执行,完成插件的安装。
 image
6  到安装插件的目录,执行命令行工具,设置程序集的权限(程序集名字为QCExcelAddIn)
caspol -machine –addfulltrust  QCExcelAddIn.dll
经过这几步,打开EXCEL,应该可以看到插件的菜单。如果仍然看不到菜单,看是不是插件被EXCEL禁用. 在DisalbeItems中把插件激活。
image 

至此,这个问题圆满解决。经过一段时间的使用,测量员要求修改一下测量数据的文件格式,如下图

image 
解析这种格式的代码比较简单,直接用正则式分解字符串即可,而上面的那个版本的格式还需要判断是奇数行还是偶数行,奇数行取零件名称,偶数行读取测量数据。

关于这个插件的注册信息,在注册表中有相应的键值对说明
插件所在的注册表键的路径是
image

值如下图所示
image


也许这个办法也不是最优化的办法,欢迎提供您的思路供大家参考学习。

免责声明:文章转载自《如何用C#制作Excel AddIn》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇架构设计:系统存储(28)——分布式文件系统Ceph(挂载)表示不同文件类型的魔术数字下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C# 将内存中的datatable数据导出为Excel(方法二,创建Excel对象导出)【转载】

上次写了一个用文件流方式将Datatable导出Excel的方法,这个方法有局限性,比如没法对Excel进行一些增加列颜色等简单的操作,现在,给大家介绍另外一种方法,用微软的Excel类。既然要用到类,那必须是你的机子要装上Excel才行呢。 public void DataTabletoExcel(System.Data.DataTable[] tmp...

mssql sqlserver 使用脚本输出excel文件的方法分享

转自:http://www.maomao365.com/?p=6683 摘要: 下文将分享使用sql脚本输出excel的方法 此脚本可以应用于 表或视图生成excel的方法,若需使用sql脚本输出excel数据,我们可将sql脚本生成视图或临时表,然后再输出excel------------------------------------输出excel...

thinkphp整合系列之phpexcel生成生成excel文件

在后台管理中会经常需要将数据生成excel表格的; php生成excel有两种方案; 一种是通过phpexcel生成xls格式的表格文件; 另一种则直接通过逗号换行生成csv格式的表格文件; 这里先讲解thinkphp整合phpexcel的过程; 示例项目:http://git.oschina.net/shuaibai123/thinkphp-bjyadm...

C#读写Excel的几种方法

1 使用Office自带的库 前提是本机须安装office才能运行,且不同的office版本之间可能会有兼容问题,从Nuget下载 Microsoft.Office.Interop.Excel 读写代码如下: 1 using Microsoft.Office.Interop.Excel; 2 using Excel = Microsoft.Offic...

无服务端纯前台导出数据到Excel-JSExcelXML.js 使用指南

JSExcelXML 使用指南 先来个效果预览  a.前端显示   b.导出excel效果 表头部分   表尾部分   1.功能描述  JsExcelXml 采用js生成excel中可显示的xml格式文本,将输出文本保存为.xls格式即可,可实现所见即所得,该版本和上个版本有较多的改动,现在的版本更加灵活,该版本分别在IE8,9,10,chrome,Fir...

【ITOO 1】将List数据导出Excel表

需求描述:在课表导入的时候,首先给用户提供模板(excel),然后将用户填写好的数据读取到list集合中。再进行判空处赋值处理,以及去重处理。这篇博客,主要介绍读取excel表和导出excel表的方法。 一、读取Excel数据到list<span style="font-family:KaiTi_GB2312;font-size:18px;">...