程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 如何用C#制作Excel AddIn

如何用C#制作Excel AddIn

編輯:關於C#
 

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

 

 

 

 

 

 


也許這個辦法也不是最優化的辦法,歡迎提供您的思路供大家參考學習。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved