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

C#如何定制Excel界面並實現與數據庫交互,

編輯:C#入門知識

C#如何定制Excel界面並實現與數據庫交互,


  Excel是微軟辦公套裝軟件的一個重要的組成部分,它可以進行各種數據的處理、統計分析和輔助決策操作,廣泛地應用於管理、統計財經、金融等眾多領域。(另外,Excel還是倫敦一所會展中心的名稱)。.NET可以創建Excel Add-In對Excel進行功能擴展,這些擴展的功能包括自定義用戶函數,自定義UI,與數據庫進行數據交互等。

一 主要的Excel開發方式

  1 VBA 

    VBA是一種Visual Basic的宏語言,它是最早的Office提供定制化的一種解決方案,VBA是VB的一個子集,和Visual Basic不同,VBA是一種宿主型語言,無論是專業的開發人員,還是剛入門的非開發人員,都可以利用VBA完成簡單或復雜的需求。

  2 Excel Addin

    Excel Addin,就像Visual Studio外接插件一樣,也可以使用一些技術為Office開發一些插件。對VBA的一些問題,一些專業的開發人員,可以使用 VisualBasic或者VisualC++等工具來引用Office的一些dll,來針對Office進行開發。開發的時候將dll注冊為com組 件,並在注冊表裡面進行注冊,這樣就可以在Excel裡直接調用這些插件。

  3 VSTO (Visual Studio Tools for Office)

    VSTO主要是對Office的一些dll進行了.NET封裝,使得我們可以使用.NET上的語言來方便的對Office的一些方法進行調用。所 以,Office開發跨入了一個新的時代,開發人員可以使用更加高級的語言和熟悉的技術來更容易的進行Office開發。 對於企業及的應用和開發,VSTO或許是首要選擇,他極大地擴展了Office應用程序的能力,使用.NET平台支持的編程語言,能夠直接訪問.NET上面眾多的類庫。具有較好的安全機制。簡化了Office插件的開發和部署。

  4 XLL

    XLL是Excel的一種外接應用程序,他使用C和C++開發,程序通過調用Excel暴漏的C接口來實現擴展功能。這種方式開發的應用程序效率高,但是難度大,對開發者自身的要求較高。開源項目Excel-DNA就是使用XLL技術開發的,能夠幫助.NET 開發人員來極大地簡化RTD函數,同步、異步UDF函數的編寫和開發。 

  5 OpenXML

    如果用戶沒有安裝Excel應用程序,或者在服務器端需要動態生成Excel文件的時候。我們可能需要直接讀取或者生成Excel文件,這種情況下,如果要對Excel文件進行各種定制化開發的話,建議使用OpenXML。NPOI開源項目可以直接讀寫Excel文件,而且兼容多個版本。

二 使用Excel Add-In構建擴展

  開發環境: 操作系統為Windows Server 2008R2 x64;Excel為Excel 2010 x64;開發工具為Visual Studio 2012旗艦版x64;數據庫為SQL Server 2008R2 x64.

  1 程序結構

  用Visual Studio 2012新建一個ExcelAddInDemo的Excel Add-In項目,並添加若干文件,程序結構如下圖:

  其中,RibbonAddIn可以定制2010的UI面板,SqlHelper.cs是一個簡單的數據庫訪問幫助類,UClog.cs,UCPaneLeft.cs,UCTaskGrid.cs,UCTaskPane.cs都為添加的自定義控件,並通過程序添加到EXCEL界面中.運行起來的界面如下:

  程序可以通過在Excel界面中輸入ID,First,Last,Email的值(對應標簽的後一個單元格),單擊用戶列表面板上的保存按鈕,將數據保存到數據庫中.

  2 RibbonAddIn設計

  我們通過RibbonAddIn.cs給Excel的Ribbon添加了一個名為CUMT的插件.RibbonAddIn面板可以通過工具條控件方便的拖放到設計界面上.RibbonAddIn.cs的屬性設置如下圖所示:

  後台代碼如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using Microsoft.Office.Tools.Ribbon;
 6 
 7 namespace ExcelAddInDemo
 8 {
 9     public partial class RibbonAddIn
10     {
11         
12         private void RibbonAddIn_Load(object sender, RibbonUIEventArgs e)
13         {
14           
15         }
16 
17         private void btnAbout_Click(object sender, RibbonControlEventArgs e)
18         {
19             System.Windows.Forms.MessageBox.Show("JackWangCUMT!");
20         }
21 
22         private void btnShow_Click(object sender, RibbonControlEventArgs e)
23         {
24             if (Globals.ThisAddIn._MyCustomTaskPane != null)
25             {
26                 Globals.ThisAddIn._MyCustomTaskPane.Visible = true;
27             }
28         }
29 
30         private void btnHide_Click(object sender, RibbonControlEventArgs e)
31         {
32             if (Globals.ThisAddIn._MyCustomTaskPane != null)
33             {
34                 Globals.ThisAddIn._MyCustomTaskPane.Visible = false;
35             }
36         }
37     }
38 }

  3 ThisAddIn邏輯編寫

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Xml.Linq;
  6 using Excel = Microsoft.Office.Interop.Excel;
  7 namespace ExcelAddInDemo
  8 {
  9     using Microsoft.Office.Tools;
 10     public partial class ThisAddIn
 11     {
 12         public CustomTaskPane _MyCustomTaskPane = null;
 13     
 14         private void ThisAddIn_Startup(object sender, System.EventArgs e)
 15         {
 16             UCTaskPane taskPane = new UCTaskPane();
 17             _MyCustomTaskPane = this.CustomTaskPanes.Add(taskPane, "我的任務面板");
 18             _MyCustomTaskPane.Width = 30;//height有問題,此處width ==height
 19             _MyCustomTaskPane.Visible = true;
 20             _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionTop;
 21 
 22             UCPaneLeft panLeft = new UCPaneLeft();
 23             _MyCustomTaskPane = this.CustomTaskPanes.Add(panLeft, "組織");
 24             _MyCustomTaskPane.Width = 200;
 25             _MyCustomTaskPane.Visible = true;
 26             _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft;
 27 
 28             UCTaskGrid panRight = new UCTaskGrid();
 29             _MyCustomTaskPane = this.CustomTaskPanes.Add(panRight, "用戶列表");
 30             _MyCustomTaskPane.Width = 200;
 31             _MyCustomTaskPane.Visible = true;
 32             _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
 33 
 34             UCLog panLog = new UCLog();
 35             _MyCustomTaskPane = this.CustomTaskPanes.Add(panLog, "日志列表");
 36             _MyCustomTaskPane.Width = 60;
 37             _MyCustomTaskPane.Visible = true;
 38             _MyCustomTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionBottom;
 39 
 40             //Hook into the workbook open event
 41             //This is because Office doesn't always have a document ready when this method is run 
 42             this.Application.WorkbookActivate += Application_WorkbookActivate;
 43             //test 
 44             //this.Application.SheetSelectionChange += Application_SheetSelectionChange;
 45         }
 46 
 47         void Application_SheetSelectionChange(object Sh, Excel.Range Target)
 48         {
 49             if (this.Application != null)
 50             {
 51                 this.Application.Caption = this.Application.ActiveCell.Address.ToString();//$A$1
 52                 //+ this.Application.ActiveCell.AddressLocal.ToString();//$A$1
 53                 //this.Application.ActiveCell.Formula = "=sum(1+2)";
 54               
 55             }
 56         }
 57 
 58         void Application_WorkbookActivate(Excel.Workbook Wb)
 59         {
 60             //using Microsoft.Office.Tools.Excel 和 using Microsoft.Office.Interop.Excel 都有worksheet等,容易混淆
 61             //string path = this.Application.ActiveWorkbook.FullName;
 62             Excel._Worksheet ws = (Excel._Worksheet)this.Application.ActiveWorkbook.ActiveSheet;
 63             ws.Cells[2, 2] = "ID2";
 64             //如何設置只讀等有待研究
 65             int r=2,c=2;
 66            //((Excel.Range)ws.Cells[r, c]).NumberFormat = format;
 67             ((Excel.Range)ws.Cells[r, c]).Value2 = "ID";
 68             ((Excel.Range)ws.Cells[r, c]).Interior.Color =System.Drawing. ColorTranslator.ToOle(System.Drawing.Color.Red);
 69             //((Excel.Range)ws.Cells[r, c]).Style.Name = "Normal";
 70             ((Excel.Range)ws.Cells[r, c]).Style.Font.Bold = true;
 71 
 72             #region format
 73             ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Bold = true;
 74             ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Italic = true;
 75             ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Color = System.Drawing.Color.FromArgb(96, 32, 0).ToArgb();
 76             ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Name = "Calibri";
 77             ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("A2", "E10")).Font.Size = 15;
 78 
 79             //border
 80             Excel.Range range = ((Microsoft.Office.Interop.Excel.Range)ws.get_Range("B2", "E3"));
 81             Excel. Borders border = range.Borders;
 82             border[Excel.XlBordersIndex.xlEdgeBottom].LineStyle =Excel. XlLineStyle.xlContinuous;
 83             border.Weight = 2d;
 84             border[Excel.XlBordersIndex.xlEdgeTop].LineStyle = Excel.XlLineStyle.xlContinuous;
 85             border[Excel.XlBordersIndex.xlEdgeLeft].LineStyle = Excel.XlLineStyle.xlContinuous;
 86             border[Excel.XlBordersIndex.xlEdgeRight].LineStyle = Excel.XlLineStyle.xlContinuous;
 87             #endregion
 88             ws.Cells[2, 4] = "First";
 89             ws.Cells[3, 2] = "Last";
 90             ws.Cells[3, 4] = "Email";
 91         }
 92         private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
 93         {
 94         }
 95 
 96         #region VSTO 生成的代碼
 97 
 98         /// <summary>
 99         /// 設計器支持所需的方法 - 不要
100         /// 使用代碼編輯器修改此方法的內容。
101         /// </summary>
102         private void InternalStartup()
103         {
104             this.Startup += new System.EventHandler(ThisAddIn_Startup);
105             this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
106         }
107         
108         #endregion
109     }
110 }

 

  ThisAddIn_Startup事件中,初始化四個面板,並對其基本屬性進行設置,停靠在上的面板我設置其Height無效,改成Width後其效果和Height預期的一樣(不知道這個底層開發人員是怎麼想的,哈哈!)另外 Excel._Worksheet ws = (Excel._Worksheet)this.Application.ActiveWorkbook.ActiveSheet;是非常關鍵的一句,我這裡足足折騰了很久,原因是using Microsoft.Office.Tools.Excel 和 using Microsoft.Office.Interop.Excel 都有worksheet元素,結構混淆了,運行時老是獲取不到Excel的ActiveWorkbook.

 

  4 UCTaskGrid設計

  UCTaskGrid是一個用戶控件,包含一個工具條和一個dataGridView1控件,其設計界面如下:

  後台代碼如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Drawing;
 5 using System.Data;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 
10 namespace ExcelAddInDemo
11 {
12     using Excel = Microsoft.Office.Interop.Excel;
13     public partial class UCTaskGrid : UserControl
14     {
15         public UCTaskGrid()
16         {
17             InitializeComponent();
18         }
19 
20         private void UCTaskGrid_Load(object sender, EventArgs e)
21         {
22             //load data
23             System.Data.DataTable dt = SqlHelper.getDateTable("select * from ACT_ID_USER", null);
24             this.dataGridView1.DataSource = dt;
25         }
26 
27         private void 保存SToolStripButton_Click(object sender, EventArgs e)
28         {
29             //核心代碼,獲取當前的worksheet
30             Excel._Worksheet ws = (Excel._Worksheet)Globals.ThisAddIn.Application.ActiveWorkbook.ActiveSheet;
31             string name = ws.Name;
32             string ID = ((string)(ws.Cells[2, 5] as Excel.Range).Value).ToString();
33             string First = ((string)(ws.Cells[2, 5] as Excel.Range).Value).ToString();
34             string Last = ((string)(ws.Cells[3, 3] as Excel.Range).Value).ToString();
35             string Email = ((string)(ws.Cells[3, 5] as Excel.Range).Value).ToString();
36             string sql = string.Format("insert into ACT_ID_USER ([ID_],[FIRST_],[LAST_],[EMAIL_]) values('{0}','{1}','{2}','{3}')", ID, First, Last, Email);
37             int rows= SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionStringLocalTransaction, System.Data.CommandType.Text,sql,null);
38             if (rows == 1)
39             {
40                 System.Windows.Forms.MessageBox.Show("saved");
41             }
42             else
43             {
44                 System.Windows.Forms.MessageBox.Show("error");
45             }
46 
47         }
48 
49         private void 打開OToolStripButton_Click(object sender, EventArgs e)
50         {
51             //refresh
52             System.Data.DataTable dt = SqlHelper.getDateTable("select * from ACT_ID_USER", null);
53             this.dataGridView1.DataSource = dt;
54         }
55     }
56 }

  5 Add-In強簽名

  通過設置程序的屬性中的簽名頁,讓VS自動生成一個簽名即可(需設置密碼)

三 最終效果演示

  為了直觀的展示,看下面的動畫:

四 猜想 Excel Service

  現在功能很強大的Excel服務器,其中一個亮點就是在Excel中進行界面設計和數據操作,然後就數據持久化到數據庫中,那麼我的猜想是,能不能通過AddIn的方式實現一個excel service功能呢,將界面設計序列化保存到數據庫中,並給一個路徑(唯一),但用戶單擊菜單(確定了路徑)後將界面設計呈現到excel中,然後用戶操作完成後,通過後台程序將數據庫保存到數據庫中.

 

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