用Excel展示SQL Server中的數據 (II): 宏與自動化


上一篇文章中,我介紹了如何將SQL Server中的數據導入Excel。其中,建立數據連接的過程是手工完成的,偶爾為之,可以接受,如果要反復操作,就不勝其煩。本文將介紹如何使用宏來自動化數據導入。

在本文中,我使用的是Excel 2007,所介紹的方法同樣適用於Excel 2010。為了使用宏,需要在Excel 2007中顯示Developer Tab。操作方法是在Excel選項對話框中,選中Show Developer tab in the Ribbon。

image_thumb[1]

1. 用宏理解Excel

為了自動化數據導入過程,需要知曉Excel在該過程中執行了哪些操作。這可以通過錄制宏來捕獲。在Developer Tab下,點擊Record Macro,將宏命名為import_data_from_sqlserver。

image8

image14

按照上一篇文章中的方法建立數據庫鏈接。不同之處在於,在Import Data話框中,點擊Properties;在Connection Properties對話框中,將Command type修改為SQL,將Command text修改為select * from test.Stat。然后連續點擊OK,完成數據導入。

image_thumb[3]

image17

在Developer Tab下點擊Stop Recording,結束宏的錄制。

image20

然后點擊Developer Tab的Visual Basic(或按下快捷鍵Alt+F11),打開的Microsoft Visual Basic視窗。在Project窗口中,雙擊Modules下的Module1,打開代碼編輯窗口。

image_thumb[9]

在代碼編輯窗口中,可見宏import_data_from_sql_server的實現。

Sub import_data_from_sqlserver()
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:=Array( _
        "OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Data Source=localhostsqlexpress;Use Procedure for Prepa" _
        , "re=1;Auto Translate=True;Packet Size=4096;Workstation ID=LIANGSHI;Use Encryption for Data=False;Tag with column collation when " _
        , "possible=False;Initial Catalog=bug_db"), Destination:=Range("$A$1")). _
        QueryTable
        .CommandType = xlCmdSql
        .CommandText = Array("select * from test.Stat")
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .SourceConnectionFile = _
        "C:Usersliangshi.000DocumentsMy Data Sourcesmytest.odc"
        .ListObject.DisplayName = "Table_mytest"
        .Refresh BackgroundQuery:=False
    End With
End Sub

灰色代碼在當前數據薄的ListObjects容器中增加了一個對象,利用Source參數指定了OLEDB數據源,並提供了數據庫連接字符串,利用Destination參數指定了數據存放於何處。黃色代碼設置新增對象的QueryTable屬性。比較重要的設置是,設定QueryTable.CommandType為xlCmdSql(SQL查詢),設定QueryTable.CommandText為待運行的SQL查詢字符串,最后調用QueryTable.Refresh函數以執行查詢。

紅色代碼指定了數據庫服務器、數據庫和SQL查詢。只要能修改它們就可以在指定數據庫上運行指定查詢,以獲得我們需要的數據。這就是本文方法的技術基礎。只是宏import_data_from_sqlserver有一個缺點:它向固定區域($A$1)插入對象,因此不能反復運行。為了避免運行時錯誤,我的策略是:不重復建立數據庫連接,而是修改已有連接,從而獲得新的查詢結果。

2. Xlsm文件

這里可以下載Book1.xlsm文件,它包含本文即將介紹的所有元素。該文件以xlsm后綴名,是因為這是一個包含宏的Excel文件。在打開它時,需要授權給宏(Macro)和數據連接(Data Connection)。

image_thumb[11]

image_thumb[12]

你如果厭倦了安全警告,可以將你的桌面加入“安全路徑”。那么從桌面打開的xlsm文件,將不顯示安全警告。

image77

image83

3. 界面:表格和按鈕

Book1.xlsm的布局如下圖所示。

image65

  1. 左上角是一個表格,其中單元格B2對應數據庫服務器,單元格B3對應數據庫,單元格B4對應SQL查詢,它們的格式都是文本(Text)。這里使用表格是為了美觀,普通的單元格也不影響功能。
  2. 左下角是一個按鈕。它的插入方法是:Developer → Insert → Button。右擊該按鈕,可以進入編輯模式:調整大小、調整位置、修改名稱、設定宏等。
  3. 右下角是一個表格,它是導入的SQL Server的數據。選中該表格中的任意單元格(圖中是單元格C5),點擊Design Tab下的Properties,彈出External Data Properties對話框,點擊Connection Properties按鈕可以查看連接的詳細屬性。該連接是我手工建立的,其名稱是my_database_connection,通過SQL查詢從數據庫中獲得數據。

image_thumb[17]%204F326AB6

image50

4. 實現邏輯:宏

按下快捷鍵Alt+F11,打開的Microsoft Visual Basic視窗。在Module1中可見宏RefreshDataConnection。它首先修改數據連接my_database_connection,主要修改內容是用單元格B2、B3和B4的值替換原有的數據庫服務器、數據庫和SQL查詢。然后,它調用數據連接my_database_connection的Refresh函數,以獲得新的數據。

Sub RefreshDataConnection()
    With ActiveWorkbook.Connections("my_database_connection").OLEDBConnection
        .BackgroundQuery = True
        .CommandText = Array(" " & Range("B4").Value & " ")
        .CommandType = xlCmdSql
        .Connection = Array("OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;" _
        , "Initial Catalog=" & Range("B3").Value & ";Data Source=" & Range("B2").Value & ";" _
        , "Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LIANGSHI;Use Encryption for Data=False;Tag with " _
        , "column collation when possible=False")
        .RefreshOnFileOpen = False
        .SavePassword = False
        .SourceConnectionFile = ""
        .SourceDataFile = ""
        .ServerCredentialsMethod = xlCredentialsMethodIntegrated
        .AlwaysUseConnectionFile = False
    End With
    ActiveWorkbook.Connections("my_database_connection").Refresh
End Sub

按鈕Refresh對應的宏就是RefreshDataConnection,這是通過編輯按鈕的屬性來設置的。

image56

image59

這樣每次點擊按鈕Refresh就可以獲得最新的數據。例如,將查詢修改為SELECT * FROM test.Stat,並單擊Refresh,可得視圖Stat的查詢結果。

image_thumb[20]

為了方便操作,我還在Sheet1中增加了宏Worksheet_Change,以響應Worksheet_Change事件。當Sheet1的內容發生變更時,Excel會調用宏Worksheet_Change。它會檢查被修改對象(Target)的單元格個數(Count)是否是1。如果是1,則進一步檢查被修改單元格是否是B4(即Row=4且Column=2),即SQL查詢是否被修改。如果SQL查詢被修改,則調用宏RefreshDataConnection以導入數據。有了這個宏,修改完SQL查詢,不用點擊Refresh,Excel就會自動加載新數據,非常方便。

image71

值得一提的是,導入的數據表格是可以拷貝到其他數據薄的。被拷貝的內容包含已導入的數據和相關的數據庫連接。這意味着,在編寫完一個SQL查詢后,可以將被修改的數據連接“另存”到另一個數據薄中,以待未來使用,而這一切都可以用拷貝和粘貼來完成。

5. 小結

本文展示了一個宏的應用實例,並可以得出以下啟示。

  1. 利用宏可以了解Excel的實現機制,這有利於更好地(手工或自動地)操作Excel。
  2. 編寫宏的一般方法是將手工操作錄制為宏,然后對錄制的宏進行修改。
  3. Excel數據薄是一個可編程的GUI:每一個單元格可以看做一個輸入框,可以插入按鈕等控件以響應用戶輸入,其內建多種事件可以激發事件處理程序。
  4. 對於許多任務,你可以用Excel來完成,而不必編寫傳統意義上的程序。你可以編寫ASP.NET網站和Silverlight應用來提供用戶界面,那很了不起。但是,你的時間是有限的,而你的客戶也不喜歡網頁上緩慢的輸入。利用Excel的宏錄制,你可以在幾分鍾內完成一個GUI程序,並提供用戶最愛的Excel風格的輸入。
  5. 宏對於VSTO的一個優點是,它完全內建於Excel。你可以在秘書和前台的筆記本電腦上進行開發和調試,而那上面絕對不會有Visual Studio。此外,相比二進制的VSTO插件,可以輕松查看並修改的宏,可以滿足一些程序員個性化定制的需要。

編程並不局限於C#和Visual Studio。Excel也提供了便捷的編程環境,運用得當,會事半功倍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM