VBA語言

第一章  VBA語言基礎 
第一節 標識符 
一.定義 
標識符是一種標識變量、常量、過程、函數、類等語言構成單位的符號,利用它可以完成對變量、常
量、過程、函數、類等的引用。   二.命名規則 
1) 字母打頭,由字母、數字和下劃線組成,如  A987b_23Abc 
2) 字符長度小於 40,(Excel2002以上中文版等,可以用漢字且長度可達 254個字符) 
3) 不能與 VB保留關鍵字重名,如 public, private, dim, goto, next, with, integer, single等 
第二節 運算符 
定義:運算符是代表 VB某種運算功能的符號。  1)賦值運算符 = 
2)數學運算符 &、 + (字符連接符 )、 +(加)、-(減)、 Mod(取餘)、 /(整除)、*(乘)、/(除)、-(負號)、^(指數) 
3)邏輯運算符 Not(非)、 And(與)、 Or(或)、 Xor(異或)、 Eqv(相等)、 Imp(隱含) 
4)關係運算符 = (相同)、 <>(不等)、>(大於)、<(小於)、 >=(不小於)、 <=(不大於)、 Like、 Is 
5)位運算符 Not(邏輯非)、 And(邏輯與)、 Or(邏輯或)、 Xor(邏輯異或)、 Eqv(邏輯等)、 Imp(隱含) 
第三節 數據類型 
VBA共有12種數據類型,具體見下表,此外用戶還可以根據以下類型用 Type自定義數據類型。 
數據類型   類型標識符   字節 
字符串型 String   $   字符長度 (0-65400) 
字節型 Byte   無   1 
布爾型 Boolean   無   2 
整數型 Integer   % 2    
長整數型  Long   & 4    
單精度型 Single   ! 4    
雙精度型 Double   # 8    
日期型  Date   無   8 公元 100/1/1-9999/12/31 
貨幣型 Currency   @ 8    
小數點型 Decimal   無   14 
變體型 Variant   無   以上任意類型,可變 
對象型 Object   無   4 
 
第四節 變量與常量 
1) VBA允許使用未定義的變量,默認是變體變量。 
2)在模塊通用說明部份,加入  Option Explicit 語句可以強迫用戶進行變量定義。 
3)變量定義語句及變量作用域  Dim  變量  as 類型   '定義爲局部變量,如  Dim     xyz as integer 
Private 變量  as 類型   '定義爲私有變量,如 Private   xyz as byte 
 

Public 變量  as 類型   '定義爲公有變量,如  Public   xyz as single 
Global  變量  as 類型   '定義爲全局變量,如  Globlal   xyz as date 
Static變量  as 類型   '定義爲靜態變量,如  Static    xyz as double  一般變量作用域的原則是,那部份定義就在那部份起作用,模塊中定義則在該模塊那作用。   4)常量爲變量的一種特例,用 Const定義,且定義時賦值,程序中不能改變值,作用域也如同變量作用域。 如下定義: Const Pi=3.1415926 as single 
第五節 數組 
數組是包含相同數據類型的一組變量的集合,對數組中的單個變量引用通過數組索引下標進行。在內 存中表現爲一個連續的內存塊,必須用Global或Dim語句來定義。定義規則如下:  Dim 數組名 ([lower to ]upper [, [lower to ]upper, ….]) as type ;Lower缺省值爲0。二維數組是按行列排列,如 XYZ(行,列)。 
除了以上固定數組外, VBA還有一種功能強大的動態數組,定義時無大小維數堀明;在程序中再利用
Redim語句來重新改變數組大小,原來數組內容可以通過加 preserve關鍵字來保留。如下例: 
Dim array1() as double : Redim array1(5) : array1(3)=250 : Redim preserve array1(5,10) 
第六節 註釋和賦值語句 
1)註釋語句是用來說明程序中某些語句的功能和作用; VBA中有兩種方法標識爲註釋語句。   9  單引號  ’ ;如:’定義全局變量;可以位於別的語句之尾,也可單獨一行 
 9  Rem ;如: Rem定義全局變量;只能單獨一行  2)賦值語句是進行對變量或對象屬性賦值的語句,採用賦值號 =,如X=123:Form1.caption=”我的窗口 ”  對對象的賦值採用: set myobject=object 或  myobject:=object 
第七節 書寫規範 
1) VBA不區分標識符的字母大小寫,一律認爲是小寫字母; 
2)一行可以書寫多條語句,各語句之間以冒號  : 分開; 
3)一條語句可以多行書寫,以空格加下劃線 _ 來標識下行爲續行; 
4)標識符最好能簡潔明瞭,不造成歧義。 
第八節 條件語句 
1) If…Then…Else語句 
If condition Then [statements][Else elsestatements]  如1:If A>B And C<D Then A=B+2 Else A=C+2   
如2:If x>250 Then x=x-100    或者,可以使用塊形式的語法:  If condition Then  [statements]  [ElseIf condition-n Then  [elseifstatements] ...  [Else  [elsestatements]]  End If 
 

如 1: 
If Number < 10 Then      Digits = 1  ElseIf Number < 100 Then      Digits = 2  Else      Digits = 3  End If 
2) Select Case…Case…End Case語句  如1:  Select Case Pid 
Case “A101” 
Price=200 
Case “A102” 
Price=300  ……  Case Else 
Price=900 
End Case 
3)Choose 函數 
choose(index, choce-1,choice-2,…,choice-n),可以用來選擇自變量串列中的一個值,並將其返回, index 
必要參數,數值表達式或字段,它的運算結果是一個數值,且界於  1 和可選擇的項目數之間。choice 必 要參數, Variant表達式,包含可選擇項目的其中之一。如: 
GetChoice = Choose(Ind, "Speedy", "United", "Federal") 
4) Switch函數 
Switch(expr-1, value-1[, expr-2, value-2 _ [, expr-n,value-n]]) 
switch函數和 Choose函數類似,但它是以兩個一組的方式返回所要的值,在串列中,最先爲 TRUE的值 會被返回。 expr 必要參數,要加以計算的  Variant 表達式。value 必要參數。如果相關的表達式爲  True, 則返回此部分的數值或表達式,沒有一個表達式爲  True, Switch 會返回一個 Null值。 
第九節 循環語句 
1) For Next語句 以指定次數來重複執行一組語句  For counter = start To end [Step step]        ' step 缺省值爲 1  [statements]  [Exit For]  [statements]  Next [counter]  如1:  For Words = 10 To 1 Step -1            ' 建立 10 次循環      For Chars = 0 To 9             ' 建立 10 次循環          MyString = MyString & Chars       ' 將數字添加到字符串中      Next Chars               ' Increment counter 
 

    MyString = MyString & " "         ' 添加一個空格  Next Words 
2) For Each…Next語句  主要功能是對一個數組或集合對象進行,讓所有元素重複執行一次語句  For Each element In group 
Statements  [Exit for]  Statements 
Next [element]  如1:  For Each rang2 In range1 
With range2.interior 
.colorindex=6  .pattern=xlSolid 
End with 
Next 
這上面一例中用到了 With…End With 語句,目的是省去對象多次調用,加快速度;語法爲:  
With object  [statements]  End With 
3)Do…loop語句 在條件爲 true時,重複執行區塊命令 
Do {while |until} condition         ' while 爲當型循環, until爲直到型循環,顧名思義,不多說啦 
Statements 
Exit do 
Statements 
Loop  或者使用下面語法  Do                ' 先 do 再判斷,即不論如何先幹一次再說  
Statements 
Exit do 
Statements 
Loop {while |until} condition 
第十節 其他類語句和錯誤語句處理 
一.其他循環語句 
結構化程序使用以上判斷和循環語句已經足夠,建議不要輕易使用下面的語句,雖然 VBA還支持。  1)  Goto line 該語句爲跳轉到line語句行 
2)  On expression gosub destinatioinlist 或者  on expression goto destinationlist 語句爲根據 exprssion表達式
值來跳轉到所要的行號或行標記 
3)  Gosub line…line…Return語句,  Return 返回到  Gosub line行,如下例:  Sub gosubtry() 
Dim num 
Num=inputbox(“輸入一個數字,此值將會被判斷循環 ”) 
If num>0 then Gosub Routine1 :Debug.print num:Exit sub 
 

Routine1: 
Num=num/5  
Return 
End sub  4) while…wend語句,只要條件爲TRUE,循環就執行,這是以前 VB老語法保留下來的,如下例:   while condition               ‘while I<50  [statements]                 ‘I=I+1  wend                   ‘Wend 
二.錯誤語句處理 
執行階段有時會有錯誤的情況發生,利用On Error語句來處理錯誤,啓動一個錯誤的處理程序。語法如下:  On Error Goto Line             ‘當錯誤發生時,會立刻轉移到line行去 
On Error Resume Next                    ‘當錯誤發生時,會立刻轉移到發生錯誤的下一行去 
On Erro Goto 0             ‘當錯誤發生時,會立刻停止過程中任何錯誤處理過程 
第十一節 過程和函數 
過程是構成程序的一個模塊,往往用來完成一個相對獨立的功能。過程可以使程序更清晰、更具結構
性。VBA具有四種過程:Sub 過程、 Function函數、 Property屬性過程和 Event事件過程。 
一.Sub過程 
Sub 過程的參數有兩種傳遞方式:按值傳遞(ByVal)和按地址傳遞 (ByRef)。如下例: 
Sub password (ByVal x as integer, ByRef y as integer) 
If y=100 then y=x+y else y=x-y  x=x+100 
End sub 
Sub call_password () 
Dim x1 as integer 
Dim y1 as integer  x1=12  y1=100  Call password (x1,y1)     ‘調用過程方式:1. Call 過程名 (參數 1, 參數 2…) ; 2. 過程名 參數 1, 參數 2…  debug.print x1,y1        ‘結果是12、 112, y1按地址傳遞改變了值,而 x1按值傳遞,未改變原值 
End sub 
二. Function函數 
函數實際是實現一種映射,它通過一定的映射規則,完成運算並返回結果。參數傳遞也兩種:按值傳
遞(ByVal)和按地址傳遞 (ByRef)。如下例: 
Function password(ByVal x as integer, byref y as integer) as boolean 
If y=100 then y=x+y else y=x-y  x=x+100  if y=150 then password=true else password=false 
End Function 
Sub call_password () 
 

Dim x1 as integer 
Dim y1 as integer  x1=12  y1=100  if password then     ‘調用函數: 1. 作爲一個表達式放在=右端  ; 2. 作爲參數使用  debug.print x1        
    end if  End sub 
三. Property屬性過程和 Event事件過程 
這是 VB在對象功能上添加的兩個過程,與對象特徵密切相關,也是 VBA比較重要組成,技術比較
複雜,可以參考相關書籍。 
第十二節內部函數 
在 VBA程序語言中有許多內置函數,可以幫助程序代碼設計和減少代碼的編寫工作。 
一.測試函數 
IsNumeric(x)           ‘是否爲數字 , 返回 Boolean結果,True or False 
IsDate(x)               ‘ 是否是日期 , 返回 Boolean結果,True or False 
IsEmpty(x)           ‘是否爲 Empty, 返回 Boolean結果,True or False 
 IsArray(x)  ‘指出變量是否爲一個數組。 
 IsError(expression) ‘指出表達式是否爲一個錯誤值  IsNu ll(expression) ‘指出表達式是否不包含任何有效數據  (Null)。 
 IsObject(identifier) ‘指出標識符是否表示對象變量 
二.數學函數 
Sin(X)、 Cos(X)、 Tan(X)、 Atan(x)  三角函數,單位爲弧度 
Log(x) 返回x的自然對數 
Exp(x)返回 ex
Abs(x) 返回絕對值 
Int(number)、Fix(number) 都返回參數的整數部分,區別: Int 將 -8.4 轉換成 -9,而  Fix 將-8.4 轉換成 -8 
Sgn(number) 返回一個  Variant (Integer),指出參數的正負號 
Sqr(number) 返回一個  Double,指定參數的平方根 
VarType(varname) 返回一個  Integer,指出變量的子類型 
Rnd(x)返回 0-1之間的單精度數據,x爲隨機種子 
三.字符串函數 
Trim (string)  去掉 string左右兩端空白 
Ltrim( string)  去掉 string左端空白 
Rtrim( string)  去掉 string右端空白 
 Len(string)  計算 string長度  Left(string, x)       取 string左段x個字符組成的字符串 
Right(string, x)       取 string右段x個字符組成的字符串 
Mid(string, start,x)     取 string從 start位開始的x個字符組成的字符串 
 Ucase(string) 轉換爲大寫 
 

 Lcase(string) 轉換爲小寫 
 Space(x)  返回x個空白的字符串  As c(string)  返回一個  integer,代表字符串中首字母的字符代碼 
 Chr(charcode) 返回 string,其中包含有與指定的字符代碼相關的字符 
四.轉換函數 
CBool(expression)    轉換爲 Boolean型  CByte(expression)    轉換爲 Byte型  CCur(expression)     轉換爲 Currency型  CDate(expression)    轉換爲 Date型  CDbl(expression)     轉換爲Double型  CDec(expression)     轉換爲 Decemal型  CInt(expression)      轉換爲 Integer型  CLng(expression)     轉換爲 Long型  CSng(expression)     轉換爲 Single型  CStr(expression)      轉換爲 String型  CVar(expression)     轉換爲 Variant型 
Va l(string)     轉換爲數據型 
Str(num ber) 轉換爲String 
五.時間函數 
Now      返回一個  Variant (Date),根據計算機系統設置的日期和時間來指定日期和時間。 
Date     返回包含系統日期的  Variant (Date)。 
Time     返回一個指明當前系統時間的  Variant (Date)。 
Timer     返回一個  Single,代表從午夜開始到現在經過的秒數。 
TimeSerial(hour, minute, second) 返回一個  Variant (Date),包含具有具體時、分、秒的時間。 
DateDiff(interval, date1, date2[,  firstdayofweek[, firstweekofyear]]) 返回 Variant (Long) 的值,表示兩個指定 日期間的時間間隔數目  Second(time) 返回一個  Variant (Integer),其值爲  0 到 59 之間的整數,表示一分鐘之中的某個秒 
Minute(time) 返回一個  Variant (Integer),其值爲  0 到 59 之間的整數,表示一小時中的某分鐘 
Hour(time)   返回一個  Variant (Integer),其值爲  0 到 23 之間的整數,表示一天之中的某一鐘點 
Day(date)  返回一個  Variant (Integer),其值爲  1 到 31 之間的整數,表示一個月中的某一日 
Month(date)  返回一個  Variant (Integer),其值爲  1 到 12 之間的整數,表示一年中的某月 
Year(date)  返回 Variant (Integer),包含表示年份的整數。 
Weekday(date, [firstdayofweek]) 返回一個  Variant (Integer),包含一個整數,代表某個日期是星期幾  
第二章  Excel VBA常用對象之使用 
第一節 文件的操作 
1) Excel文件 
1.1 新建與打開  一.新建  Workbooks.Add 
 

二.打開 
Workbooks.Open "路徑 /" & "文件名 .xls" 
三.文件打開對話框的使用 
Application.GetOpenFilename(fileFilter:="Excel files(*.xls),*.xls,All files (*.*),*.*") 
示例 : 
flag = False  Do While Not flag                                  ' 對話框打開已有 Excel文件    fm = Application.GetOpenFilename(fileFilter:=" Excel files(*.xls),*.xls, All files (*.*),*.*") 
 If fm <> False Then      Workbooks.Open fm      Set bb = ActiveWorkbook      '把 bb變量設爲當前活動工作簿對象,打開一工作簿時,該工作簿自動爲當前活動工作簿      flag = True    End If  Loop 
1.2 保存與關閉  一.保存  Workbooks("文件.xls").Save 
二.另存對話框的使用 
Application.GetSaveAsFilename(fileFilter:="Excel files (*.xls),*.xls,All files (*.*),*.*") 
示例 : 
flag = False  Do While Not flag                 ' 循環要求必須輸入文件名或選擇文件名    fm = Application.GetSaveAsFilename(fileFilter:=" Excel files (*.xls),*.xls,All files (*.*),*.*") 
 If fm <> False Then       activeworkbook.SaveAs fm     ' 當前活動工作簿另存       flag = True    End If  Loop 
三.關閉 
1.單個文件關閉  Workbooks("filename.xls").Close  2.所有該 Excel程序打開的文件都關閉  Workbooks.Close 
如果文件使用中改動過內容 , 那麼該命令使用時會彈出提示對話框 , 詢問是否保存 . 
如果要想不彈出提示對話框,可以使用第三或第四種文件關閉方法 , 或者如下示例 . 
示例 : 
 

關閉工作簿“ Book1.xls”,但不提示用戶保存所作修訂。“ Book1.xls”中的所有修訂都不  會保存。  Application.DisplayAlerts = False   '信息警告關閉 
Workbooks("BOOK1.XLS").Close 
Application.DisplayAlerts = True    '信息警告開啓 
四.關閉同時保存 
Workbooks("filename.xls").Close savechanges:=True 
五.關閉同時不保存 
Workbooks("filename.xls").Close savechanges:=False 
六 .Excel程序的關閉  Application.Quit 
說明 : 
使用本方法時,如果有未保存的工作簿處於打開狀態,則  Microsoft Excel 將彈出一個對話  框,詢問是否要保存所作修改。 
爲防止這一情況出現,可在使用  Quit 方法前保存所有的工作簿或將 DisplayAlerts 屬性設  置爲  False。如果該屬性爲  False,則 Microsoft Excel 退出時,即使存在未保存的工作簿   退出,也不會顯示對話框,而且不保存就退出。如果將一個工作簿的  Saved 屬性設置爲 Tr  ue,但是並沒有將其保存到磁盤上,則 Microsoft Excel 在退出時不會提示保存該工作簿。 
七.工作簿的密碼保護與撤銷   保護工作簿使其不至被修改。  Workbooks(“工作簿名 ”).Protect (Password, Structure, Windows) 
Password   Variant 類型,可選。爲一個字符串,該字符串爲工作表或工作簿指定區分大小寫的密碼。如 果省略本參數,不用密碼就可以取消對該工作表或工作簿的保護。否則,必須指定密碼,通過密碼來取消 對該工作表或工作簿的保護。如果忘記了密碼,就無法取消對該工作表或工作簿的保護。最好在安全的地 方保存一份密碼及其對應文檔名的列表。  Structure   Variant 類型,可選。如果爲  True,則保護工作簿結構(工作表的相對位置)。默認值爲  False。 
Windows   Variant 類型,可選。如果爲  True,則保護工作簿窗口。如果省略本參數,則窗口不受保護   如:Workbooks(“學生檔案”).protect ”1234” 
Workbooks(“學生檔案”).Unprotect (Password) 
Password   Variant 類型,可選。指定用於解除工作表或工作簿的保護的密碼,此密碼是區分大小寫的。 如果工作表或工作簿不設密碼保護則忽略本參數。如果對工作表省略此參數,而該工作表又設有密碼保護, Microsoft Excel 將提示您要輸入密碼。如果對工作簿省略此參數,而該工作簿又設有密碼保護,本方法將 失敗。 
1.3 示例 
示例 :(使用了4個文件,宏程序文件操作了另外三個文件,還涉及到文件打開另存對話框) 
一. 在 test.xls文件中編寫一個宏程序test,完成以下內容.打開當前目錄下 test1.xls  文件,計算 sheet1工作表上單元格 a1到a10的數據剩上 (0-1)的隨機數,計算結果保存在一個新 
 

建工作簿的 sheet1的 a1到a10上,且結果還要保存在一個任意打開的 Excel文件下,示例中打開  test2.xls文件, 完成後關閉Excel程序. 
test.xls 模塊中  Sub test() 
 Dim i As Integer, flag As Boolean, fm 
    Dim aa, bb, cc, temp 
    Application.ScreenUpdating = False  '屏幕刷新關閉 
    Application.DisplayAlerts = False    '信息警告關閉 
     
    Workbooks.Open ThisWorkbook.Path & "/test1.xls"  '打開文件 test1.xls 
    Set aa = ActiveWorkbook.Sheets("Sheet1") 
    flag = False 
    Do While Not flag                                  ' 對話框打開已有 Excel文件 
        fm = Application.GetOpenFilename(fileFilter:="Excel files (*.xls),*.xls, _  All files (*.*),*.*")          If fm <> False Then 
            Workbooks.Open fm 
            Set bb = ActiveWorkbook 
            flag = True 
        End If 
    Loop 
         
    Workbooks.Add 
    Set cc = ActiveWorkbook 
    With cc.Sheets("Sheet1") 
        For i = 1 To 10 
            temp = aa.Cells(i, 1) * Int((10 * Rnd) + 1) ' 生成 1 到 10 之間的隨機數值 
            .Cells(i, 1) = temp 
            bb.Sheets(1).Cells(i, 1) = temp 
        Next 
    End With 
     
    flag = False 
    Do While Not flag                 ' 循環要求必須輸入文件名或選擇文件名 
        fm = Application.GetSaveAsFile name(fileFilter:="Excel files (*.xls),*.xl _  s,All files (*.*),*.*")          If fm <> False Then 
            cc.SaveAs fm 
            flag = True 
        End If 
    Loop 
     
    bb.Save   '保存 
 Set aa = Nothing: Set bb = Nothing: Set cc = Nothing      '設置對象變量爲空 
 

    Application.Quit   '關閉Excel 
    Application.ScreenUpdating = True   '屏幕刷新關閉 
    Application.DisplayAlerts = True    '信息警告開啓  End Sub 
2) 文本文件  2.1 打開與新建  Open 語句  能夠對文件輸入/輸出 (I/O)。  語法  Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength] 
Open 語句的語法具有以下幾個部分:  部分 描輀  pathname 必要。字符串表達式,指定文件名,該文件名可能還包括目錄、文件夾及驅動器。  mode 必要。關鍵字,指定文件方式,有  Append、 Binary、 Input、 Output、或  Random 方 式。如果未指定方式,則以  Random 訪問方式打開文件。  access 可選。關鍵字,說明打開的文件可以進行的操作,有  Read、Write、或  Read Write 操 作。  lock 可選。關鍵字,說明限定於其它進程打開的文件的操作,有  Shared、Lock Read、Lock  Write、和  Lock Read Write 操作。  filenumber 必要。一個有效的文件號,範圍在  1 到 511 之間。使用  FreeFile 函數可得到下一個 可用的文件號。  reclength 可選。小於或等於  32,767(字節)的一個數。對於用隨機訪問方式打開的文件,該值 就是記錄長度。對於順序文件,該值就是緩衝字符數。  
說明 
對文件做任何  I/O 操作之前都必須先打開文件。 Open 語句分配一個緩衝區供文件進行 I/O 之用,
並決定緩衝區所使用的訪問方式。 
[新建] 如果  pathname 指定的文件不存在,那麼,在用   Append、 Binary、 Output、或  Random 方
式打開文件時,可以建立這一文件。 
如果文件已由其它進程打開,而且不允許指定的訪問類型,則  Open 操作失敗,而且會有錯誤發生。 
如果 mode 是  Binary 方式,則  Len 子句會被忽略掉。 
重要 
在  Binary、 Input 和  Random 方式下可以用不同的文件號打開同一文件,而不必先將該文件關閉。
在  Append 和  Output 方式下,如果要用不同的文件號打開同一文件,則必須在打開文件之前先關閉該 文件。
2.2 讀入與寫出 
2.2.1讀入 
Input #filenumber, varlist  從已打開的順序文件中讀出數據並將數據指定給變量 
Get [#]filenumber, [recnumber], varname  將一個已打開的磁盤文件讀入一個變量之中  2.2.2寫入  Write #filenumber, [outputlist] 
 

將數據寫入順序文件,以雙引號"數據"逗號,分隔數據 
Print #filenumber, [outputlist]  將格式化顯示的數據寫入順序文件中 
Put [#]filenumber, [recnumber], varname  將一個變量的數據寫入磁盤文件中。 
2.3關閉 
Close [filenumberlist] 關閉 Open 語句所打開的輸入/輸出 (I/O) 文件 
注意 : 
如果今後想用 Input # 語句讀出文件的數據,就要用  Write # 語句而不用  Print # 語句將數據寫入文件。 因爲在使用  Write # 時,將數據域分界就可確保每個數據域的完整性,因此可用  Input # 再將數據讀出來。 使用  Write # 還能確保任何地區的數據都被正確讀出。 Write 與  Print # 語句不同,當要將數據寫入文件 時,Write # 語句會在項目和用來標記字符串的引號之間插入逗號。Write # 語句在將 outputlist 中的最後 一個字符寫入文件後會插入一個新行字符,即回車換行符,(Chr(13) + Chr(10)) 
2.4其他文件函數 
LOF(filenumber)  返回一個  Long,表示用  Open 語句打開的文件的大小,該大小以字節爲  單位。  EOF(filenumber)  返回一個  Integer,它包含  Boolean 值 True,表明已經到達爲  Random  或順序 Input 打開的文件的結尾。  Loc(filenumber)   返回一個  Long,在已打開的文件中指定當前讀/寫位置 
Seek(filenumber)  返回一個  Long,在  Open 語句打開的文件中指定當前的讀/寫位置 
2.5 示例 
要求: 打開一文本文件 test1.txt, 已知其內容爲空格分隔 , 要求把其中每行首個數據寫入Excel 宏程序文件 的表1中, 再把數據寫入新建文件 test2.ini中 
Sub test() 
 Dim Fm, i As Long, j As Long, k As Long 
 Dim TT, T1 
 On Error Resume Next 
  
 Fm = Application.GetOpenFilename("Text Files (*.txt), *.txt") 
 If Fm = False Then Exit Sub              ' 取消選擇文件則退出   k = FreeFile 
 Open Fm For Input As #k                  ' 以隨機只讀的方式打開文件 
  
 f2 = FreeFile 
 Open "c:/test2.ini" For Output As #f2        ' 以隨機方式新建一個不存在的文件 
  
 j = 1 
 W ithWo rksheets("sheet1")
  
 

 Do While Not EOF(k)                      ' 循環讀至文件最後一行        Line Input #k, TT                    ' 讀入一行數據並將其賦予某變量 
      T1 = Split(TT)                       ' 以文本中空格來分開這個字符串並賦值給變量,請參考 split函數幫助        .Cells(j, 1) = T1(0) 
      Print #f2, T1(0) 
      j = j + 1 
 Loop
 EndW ith
  
 Close #k                                 ' 關閉文件 
 Close #f2                                ' 關閉文件 
End Sub 
3) Access文件 
使用 VBA來訪問數據庫,其實就是通過一定方法藉助數據庫引擎來訪問,關鍵是使用什麼方法來使
用引擎。目前訪問 ACCESS數據庫常用的有 DAO和 ADO方法,DAO就是 Database Access Object(數據庫 訪問對象 )的英文縮寫, DAO是老式的 , 它目前還在使用的原因是向下兼容和 ADO在一些地方還沒有取代 DAO的功能。 ADO是 ActiveX Data Object(數據控件對象)的英文縮寫,是目前較新和功能較強的方法。 
通過 DAO或ADO可以訪問多種類型的數據庫,包括 Access、SQL Server、 Oracle等,也可訪問應用
程序的文件,如Excel文件、文本文件及 Email和 NEWS的文件。實際上利用控件來鏈接數據庫,其概念 大致相同,首先都需創建鏈接,其後用 Open方法產生各種類型的數據集對象,再對數據集對象操作來使 用數據庫內容。 
3.1 DAO使用的步驟及方法  (1). 引用 DAO類型庫 
從 VBE的”工具/引用”菜單中選擇可引用“Microsoft DAO 3.6 Object Library”項 . 
設置DAO數據類型變量
(2). 定義 DAO對象變量 
1) Dim db As Database, Database(數據庫 )變量對應於 Access數據庫 . 
2) Dim rs As RecordSet, RecordSet(記錄集)變量對應於 Access數據庫的一個表或子表 .  多定義爲全局變量,以供程序多處使用。 
(3). 打開數據庫 
Set db = OpenDatabase (Thisworkbooks.path & "/數據庫名礀.mdb" )   ‘用 DAO怎麼樣打開有密碼的 ACCESS 數據庫  Set dbTemp = OpenDatabase("C:/db.mdb", False, False, ";PWD=1234 5")   
(4).打開表或建立表的子表  A. 建立表的子表 
Set rs = db.OpenRecordset("select * from 表名")  
B. 打開表 
Set RS = DB.OpenRecordset("表名", dbOpenDynaset) 
Opendatabase 方法是打開數據庫並返回此數據庫的 database對象,其語法如下: 
 

Set database的對象變量=opendatabase ([路徑及數據庫名礀 ],[除外性],[只讀 ])  除外性:由true和 false值所構成,當值爲 true時代表僅允許唯一的使用者使用數據庫。  只讀:由 true和 false值所構成,爲 true代表數據庫僅提供讀取的服務 
Openrecordset方法用來創建一個新的 recordset對象,語法爲: 
Set recordset 對象變量=數據庫變量.openrecordset(來源,種類 )  recordset種類有5種,分別爲:表(table)、動態集(dynaset)、快照集(snapshot)、動態(dynamic)、正 向(forward-only),其中常用的時動態集(dynaset)實際上是引用一個或多個表中數據記錄的集合,是功 能最強的數據記錄集合類型,也是默認值。 
(5). 操作數據庫記錄 
對記錄的操作就是使用記錄集的對象方法和屬性來實現,特附錄常用屬性和方法如下。 
記錄集對象的屬性和方法: 
rs.Recordcount屬性 用來記錄目前數據記錄的數量,如判斷數據庫是否爲空  rs.EOF 屬性 是否是記錄的尾  rs.BOF 屬性 是否是記錄的頭  rs.Nomatch 屬性 返回上次查找成功與否 
rs.Move n 方法 移動到第 n 條記錄  rs.Movenext 方法 移動到下一條記錄  rs.MovePrevious 方法 移動到上一條記錄  rs.Movefirst 方法 移動到第一條記錄  rs.Lastfirst 方法 移動到最後一條記錄  rs.Delete 方法 刪除當前記錄  rs.Edit 方法 修改當前記錄 (步驟爲三步: 1. 用 edit方法設置爲修改狀態;2. 將數據分別賦到記錄的各字 段; 3.用Updata方法,把記錄更新到數據庫中)  rs.AddNew 方法 添加記錄   (添加記錄分三步:1. 用AddNew方法添加一個新的空白記錄;2. 將數據分別賦到記錄的各字段;3.用 Updata方法,把記錄更新到數據庫中去)  rs.Updata 方法 更新內容到數據庫中  rs.Findfirst "字段名 = ' " & “查找內容 ” & " ' "   方法 查找記錄中字段與內容相配的首條記錄  rs.Findnext 方法 查找下一個匹配記錄  rs.FindLast 方法 查找最後一個匹配記錄  rs.FindPrevious方法 查找前一個匹配記錄  rs.Close 方法 關閉 記錄集關閉鏈接 
字段集的屬性方法: 
rs. Fields.Count 屬性 字段數目  rs. Fields(n) 第 n+1個字段 , Fields(0) 表示第一個字段  rs. Fields.Delete(Name As String) 方法 刪除字段  rs. Fields.Append (Object As Object) 方法 添加字段  rs. Fields.Refresh 方法 更新 
字段的屬性方法 :  rs. Fields(n).Name 
 

rs. Fields(n).Size  rs. Fields(n).Type  rs. Fields(n).Fieldsize  rs. Fields(n).value 
示例: 打開一個數據庫,建立瀏覽, 查詢, 修改, 刪除, 添加等功能。   Option Explicit 
Public totalRecs As Long, curRecNo As Long        '用於記住 總記錄數 和 當前記錄號 
Public DB1 As Database, RS1 As Recordset 
Private Sub UserForm_Initialize()   '窗口顯示 
 Set DB1 = OpenDatabase(ThisWorkbook.Path & "/pallet.mdb") 
    Set RS1 = DB1.OpenRecordset("pallet", dbOpenDynaset) 
    If RS1.EOF And RS1.BOF Then 
        MsgBox "Database is Null." 
        cmdExit_Click 
    Else 
        RS1.MoveLast                ' 指針移動到最後記錄,以便統計記錄總數 
        RS1.MoveFirst 
        totalRecs = RS1.RecordCount 
        curRecNo = 1 
        SetData                     ' 設置窗口參數,按鈕是否可用 
    End If  End Sub 
Private Sub cmdFirst_Click()           ' 第一條記錄      RS1.MoveFirst 
    curRecNo = 1 
    SetData  End Sub 
Private Sub cmdLast_Click()           ' 最後一條記錄      RS1.MoveLast 
    curRecNo = totalRecs 
    SetData  End Sub 
Private Sub cmdPrevious_Click()     '前一條記錄      RS1.MovePrevious 
    curRecNo = curRecNo - 1 
    SetData  End Sub 
Private Sub cmdNext_Click()         ' 下一條記錄      RS1.MoveNext 
    curRecNo = curRecNo + 1 
    SetData  End Sub 
Private Sub cmdAdd_Click()          ' 增加一條記錄      Dim i As Integer 
    RS1.AddNew 
 

    For i = 1 To 5 
        RS1.Fields(i) = Me.Controls("txt" & i) 
    Next i 
    RS1.Update 
    totalRecs = totalRecs + 1 
    curRecNo = totalRecs 
    RS1.MoveLast 
    SetData  End Sub 
Private Sub cmdDelete_Click()       '刪除當前記錄      RS1.Delete 
    RS1.MoveNext 
    If RS1.EOF = True Then 
        RS1.MovePrevious            ' 指針到底就朝前移 
        curRecNo = totalRecs - 1 
    End If 
    totalRecs = totalRecs - 1 
    SetData  End Sub 
Private Sub cmdModify_Click()       '修改當前記錄      Dim i As Integer 
    RS1.Edit 
    For i = 1 To 5 
        RS1.Fields(i) = Me.Controls("txt" & i) 
    Next i 
    RS1.Update  End Sub 
Private Sub cmdFind_Click()          ' 查找記錄,與第一個文本框內容相等  
 RS1.FindFirst "palletno='" & txt1.Text & "'" 
    If RS1.NoMatch Then 
        MsgBox "Sorry, find Nothing!" 
    Else 
        curRecNo = RS1.AbsolutePosition + 1 
        SetData 
    End If  End Sub 
Private Sub cmdClear_Click()         ' 清除顯示內容      Dim i As Integer 
    For i = 1 To 5 
        Me.Controls("txt" & i) = "" 
    Next i  End Sub 
Private Sub cmdExit_Click()          ' 退出窗口      RS1.Close 
    DB1.Close 
    Unload Me 
 

End Sub 
Sub SetData()                        ' 窗口數據設置      Dim i As Integer 
    txtCurRecNo.Text = curRecNo 
    cmdFirst.Enabled = curRecNo > 1 
    cmdPrevious.Enabled = curRecNo > 1 
    cmdLast.Enabled = curRecNo < totalRecs 
    cmdNext.Enabled = curRecNo < totalRecs 
    For i = 1 To 5 
        Me.Controls("txt" & i).Text = RS1.Fields(i) 
    Next  End Sub 
3.2 ADO使用的步驟及方法  (1). 引用 ADO類型庫 
從 VBE的”工具/引用”菜單中選擇可引用“Microsoft ActiveX Data Object 2.5 Library”項 . 
(2). 定義和生成ADO對象 
1) Dim Cnn As New ADODB.Connection     ‘數據庫連接 Connection對象變量 
2) Dim Rst As New ADODB.Recordset      ‘數據庫記錄集對象變量 
3) Dim Fld As ADODB.Field              ‘記錄字段對象變量 
(3). 打開數據庫 
Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & This Workbook.Path & "/CONTACT1.MDB;"  用定義生成的數據庫連接對象的open方法,打開一個數據庫。如果要用ADO打開一個加密碼的數據庫, 方法如下:  CNN.Open "provider=Microsoft.jet.OLEDB.4.0;Data Source=" &  ThisWorkbook.Path & "/CONTACT1.MDB;" &  ";Jet OLEDB:Database Password=123" 
(4).打開表或建立表的子表 
Rst.Open "SELECT 字段名[,字段名] FROM 表名",Cnn, adOpenKeyset, adLockOptimistic  用記錄集對象的open方法,打開或生成一個數據庫的表或子表記錄。  如:Rs1.Open "Person", Cnn, adOpenKeyset, adLockOptimistic   '取得聯繫人表所有記錄集內容 
(5). 操作數據庫記錄 
對記錄的操作就是使用記錄集的對象方法和屬性來實現,屬性和方法其實與 DAO的相似,這裏就不多說。 看下面示例,儘快學會使用 ADO.  示例 : 打開一個數據庫,建立瀏覽, 修改, 刪除, 添加和篩選等功能。使用 ADO修改和刪除記錄時,最關鍵 一條就是主關鍵字段不能重複,所以我們需要建立主關鍵字段爲自動編號類型 (Access自動編號 ),這樣就 不會重複,否則出錯! 
Option Explicit 
Public totalRecs As Long, curRecNo As Long        '用於記住 總記錄數 和 當前記錄號 
Public Cnn As ADODB.Connection                ' 定義全局數據庫對象變量 
Public Rs1 As ADODB.Recordset 
 

'窗體啓動程序 
Private Sub UserForm_Initialize()      Set Cnn = New ADODB.Connection                       ' 創建一個連接和打開  Cnn 連接 
    Set Rs1 = New ADODB.Recordset                         ' 創建一個記錄集 
    Cnn.Open  "Provider=Microsoft.Jet.O LEDB.4.0; DataSour ce=" &ThisWorkbook .Path&  "/CONTACT1.MDB;"      Rs1.Open "Person", Cnn, adOpenKeyset, adLockOptimistic          ' 取得聯繫人表所有記錄集內容 
    Rs1.MoveLast 
    totalRecs = Rs1.RecordCount 
    curRecNo = 1 
    Rs1.MoveFirst 
    Call dis_form                                               ' 顯示數據記錄到窗體  End Sub 
'****[第一條]按鈕程序 ****  Private Sub CommandButton1_Click()      Rs1.MoveFirst      curRecNo = 1      Call dis_form  End Sub 
'****[上一條]按鈕程序 ****  Private Sub CommandButton2_Click()      Rs1.MovePrevious      curRecNo = curRecNo - 1      Call dis_form  End Sub 
'****[下一條]按鈕程序 ****  Private Sub CommandButton3_Click()      Rs1.MoveNext      curRecNo = curRecNo + 1      Call dis_form  End Sub 
'****[最後一條]按鈕程序 ****  Private Sub CommandButton4_Click()      Rs1.MoveLast      curRecNo = totalRecs      Call dis_form  End Sub 
'****[刪除]按鈕程序 ****  Private Sub CommandButton5_Click()      Rs1.Delete      totalRecs = totalRecs - 1 
 

    Rs1.MoveNext 
    If Rs1.EOF = True Then 
        Rs1.MovePrevious 
        curRecNo = curRecNo - 1 
    End If 
    Rs1.Update            ' 更新數據記錄集,這點與DAO方法不同,  DAO刪除後不需更新 
    Call dis_form  End Sub 
'**** [關閉]按鈕  **** 
Private Sub CommandButton6_Click()      Rs1.Close 
    Cnn.Close 
    Set Rs1 = Nothing: Set Cnn = Nothing         ' 刪除對象 
    Unload Me                               ' 關閉窗體  End Sub 
'****[更新]按鈕程序 ****  Private Sub CommandButton8_Click()      On Error Resume Next      Rs1.Fields(1) = TextBox1.Text      Rs1.Fields(2) = TextBox2.Text      Rs1.Fields(3) = TextBox3.Text      Rs1.Fields(4) = TextBox4.Text      Rs1.Fields(5) = TextBox5.Text      Rs1.Fields(6) = TextBox6.Text      Rs1.Fields(7) = TextBox7.Text      Rs1.Fields(8) = TextBox8.Text      Rs1.Update  End Sub  '****[查找]按鈕程序 ****  Private Sub CommandButton10_Click()      Dim Rs2 As New ADODB.Recordset      Dim i As Integer  Rs2.Open "select * from person where 聯繫人編號  like " & TextBox1.Text, Cnn, adOpenKeyset,  adLockOptimistic        ‘SQL語言使用,查詢生成新的記錄集      If Rs2.EOF And Rs2.BOF Then          MsgBox "Not find!"      Else         Sheets(1).Cells.ClearContents         For i = 0 To Rs2.Fields.Count - 1          Sheets(1).Cells(1, i + 1) = Rs2.Fields(i).Name         Next         Sheets(1).Cells(2, 1).CopyFromRecordset Rs2         MsgBox "The find result is displayed in Excel."      End If 
 

    Rs2.Close 
    Set Rs2 = Nothing  End Sub 
'****[添加]按鈕程序 ****  Private Sub CommandButton9_Click()      Rs1.AddNew      '添加一條記錄,注意Fields(0)字段爲主鍵且 Access自動編號,這可以保證添加內容可以重複,否則出 錯      totalRecs = totalRecs + 1      Rs1.Fields(1) = TextBox1.Text      Rs1.Fields(2) = TextBox2.Text      Rs1.Fields(3) = TextBox3.Text      Rs1.Fields(4) = TextBox4.Text      Rs1.Fields(5) = TextBox5.Text      Rs1.Fields(6) = TextBox6.Text      Rs1.Fields(7) = TextBox7.Text      Rs1.Fields(8) = TextBox8.Text      Rs1.Update      curRecNo = totalRecs      Call dis_form  End Sub 
'****在窗體上顯示當前記錄*****  Private Sub dis_form()      TextBox1.Text = Rs1.Fields(1)      TextBox2.Text = Rs1.Fields(2)      TextBox3.Text = Rs1.Fields(3)      TextBox4.Text = Rs1.Fields(4)      TextBox5.Text = Rs1.Fields(5)      TextBox6.Text = Rs1.Fields(6)      TextBox7.Text = Rs1.Fields(7)      TextBox8.Text = Rs1.Fields(8)      CommandButton1.Enabled = curRecNo > 1      CommandButton2.Enabled = curRecNo > 1      CommandButton3.Enabled = curRecNo < totalRecs      CommandButton4.Enabled = curRecNo < totalRecs      TextBox9 = curRecNo  End Sub 
(6).數據庫使用 SQL查詢語言 
數據庫一般都提供了關連式數據庫的查詢語言 SQL (Structured Query Language), 它是一種非常口語
化、既易學又易懂的語法。此語言幾乎是每個數據庫系統都必須提供的,用以表示關連式的操作,包含了 資料的定義 (DDL)以及資料的處理 (DML)。 
對於 SQL語言的使用,請參考別的專業教程,本文就簡約介紹一下,示例中也僅用到一點SQL語言。 
(6.1)資料定義 DDL(Data Definition Language)   
 

    資料定義語言是指對資料的格式和形態下定義的語言,他是每個數據庫要建立時候時首先要面對的, 舉凡資料分哪些表格關係、表格內的有什麼字段元主鍵、表格和表格之間互相參考的關係等等,都是在開 始的時候所必須規劃好的。   如建表格:Create Table table_name (column1 DATATYPE [NOT NULL] [NOT NULL PRIMARY KEY],  column2 DATATYPE [NOT NULL],...) 
(6.2)資料操作 DML(Data Manipulation Language) 
    資料定義好之後接下來的就是資料的操作。資料的操作不外乎增加資料( insert)、 查詢資料( query)、 更改資料( update) 、刪除資料( delete)四種模式,以下分別介紹他們的語法:  增加資料: INSERT INTO table_name (column1,column2,...) VALUES ( value1,value2, ...)  查詢資料: SELECT * FROM table_name WHERE conditions  更改資料:UPDATE table_name SET column1=''xxx'' WHERE conditoins  刪除資料: DELETE FROM table_name WHERE conditions 
4) 文件其它操作  4.1) 判斷文件存在 
使用  Dir 函數判斷 , 格式: Dir [(pathname    [, attributes] ) ]  Dir 會返回匹配 pathname 的第一個文件名。示例如下 .     strfile = Dir(ThisWorkbook.Path & "/filename.xls")      '檢查文件是否存在  If strfile <> "" Then    ‘存在就打開     Workbooks.Open ThisWorkbook.Path & "/filename.xls"  Else ‘文件不存在就警告                    MsgBox "文件不存在 ", vbOKOnly, "警告"  End If 
4.2) 搜查文件 
使用 Application.FileSearch方法  示例如下 :   pp = "D:/Temp": ff = 0  With Application.FileSearch    .NewSearch    .LookIn = pp    .Filename = "prn*.tmp"  ‘查找文件 prn*.tmp  *爲指代符 
 If .Execute() > 0 Then ff = .FoundFiles.Count 
End With 
MsgBox pp & " 找到  " & ff & " 個檔案 !" 
4.3) 刪除文件  使用  kill 方法  示例如下 : kill(“c:/mytest.txt”) 
4.4) 取得文件日期屬性
使用  FileSystem object對象實現 , 示例函數如下 
Function FileDate(filespec, datetype) 
 Dim fs, f, s 
 

 Set fs = CreateObject("Scripting.FileSystemObject") 
 Set f = fs.GetFile(filespec)    Select Case datetype      Case 1: FileDate = f.DateCreated         ' 檔案建立日期      Case 2: FileDate = f.DateLastAccessed    ' 存取日期      Case 3: FileDate = f.DateLastModified    '修改日期    End Select  End Function 
4.5) FileSystemObject文件系統對象的使用 
FileSystemObject (FSO,下面簡礀爲 FSO) 對象模型,具有大量的屬性、方法和事件,使用面向對象
的“ object.method”語法,來處理文件夾和文件,可以在Office 2000 以後版本使用。 FileSystemObject 並 不是 VBA 的一部分,它是以一個 COM 組件的形式提供,可以在VB、 VBA、 VBScript 中使用。 
 FSO對象模型可以創建、改變、移動和刪除文件夾,或探測特定的文件夾是否存在,若存在,還可以
找出有關文件夾的信息,如名礀、被創建或最後一次修改的日期,等等。 FSO 對象模型還使文件處理變得 很容易。可以創建文件,插入和改變數據,以及輸出(讀取)數據。 FSO 對象模型,支持通過  TextStream  對象來創建和操作文本文件,但不支持二進制文件的創建或操作,這可以用 VBA語句完成。 
使用 FileSystemObject 對象模型進行文件操作的步驟是:  1. 使用  CreateObject 方法來創建  FileSystemObject 對象; 
2. 在新創建的對象上使用適當的方法; 
3. 訪問對象的屬性。 
下面代碼顯示如何創建  FileSystemObject 實例:  Dim fso 
Set fso = CreateObject("Scripting.FileSystemObject")  在這個示例中, Scripting 是類型庫的名字,而  FileSystemObject 則是想要創建的對象的名字。 
使用 FSO 處理文件夾的任務和方法  創建文件夾       FileSystemObject.CreateFolder  刪除文件夾       Folder.Delete 或 FileSystemObject.DeleteFolder  移動文件夾       Folder.Move 或 FileSystemObject.MoveFolder  複製文件夾       Folder.Copy 或 FileSystemObject.CopyFolder  檢索文件夾       Folder.Name  如果文件夾在驅動器上存在,則找出它         FileSystemObject.FolderExists  獲得現有Folder 對象的實例         FileSystemObject.GetFolder  找出文件夾的父文件夾名     FileSystemObject.GetParentFolderName  找出系統文件夾的路徑     FileSystemObject.GetSpecialFolder    
FSO 中寫數據到文本文件的方法 
向打開的文本文件寫數據,不用後續一個新行字符   Write 
向打開的文本文件寫數據,後續一個新行字符  WriteLine 
向打開的文本文件寫一個或多個空白行  WriteBlankLines 
FSO 中讀取文本文件的方法 
 

從文件讀取指定數量的字符      Read 
讀取一整行(一直到但不包括新行字符)      ReadLine 
讀取文本文件的整個內容   ReadAll 
FSO 中移動、複製和刪除文件的方法  移動文件  File.Move 或 FileSystemObject.MoveFile  複製文件  File.Copy 或 FileSystemObject.CopyFile  刪除文件 File.Delete 或 FileSystemObject.DeleteFile 
使用 FSO 處理文件、文件夾比使用 VBA 語句的方法具有更易操作的特點, FSO 除了不能處理二進制文 件,其文件和文件夾處理的方法也更完備,更直觀和易於使用。 
第二節 工作表操作 
在文件操作一節已經講了 Excel工作簿文件的打開、新建、保存和關閉了,這裏再講文件下的表格操作。            1) 新建與刪除  新建工作表、圖表或宏表。新建的工作表將成爲活動工作表。  Sheets.Add (Before, After, Count, Type)  說明: 
Before   Variant 類型,可選。指定工作表對象,新建的工作表將置於此工作表之前。 
After   Variant 類型,可選。指定工作表對象,新建的工作表將置於此工作表之後。 
Count   Variant 類型,可選。要新建的工作表的數目。默認值爲  1。 
Type   Variant 類型,可選。指定工作表類型。可爲以下  XlSheetType 常量之一: xlWorksheet、 xlChart、 xlExcel4MacroSheet 或 xlExcel4IntlMacroSheet。默認值爲  xlWorksheet。  如果 Before 和  After 兩者均省略,則新建的工作表將插入到活動工作表之前。  示例: Sheets.Add after:=Sheets(Sheets.Count)   該語句可以在最後一個工作表後增加一個新表 
刪除工作表 
Sheets(“工作表名 ”).Delete  示例:在工作表末新建一個和刪除倒數第二個表。  
Sub MySht() 
    Application.DisplayAlerts = False   '關閉刪除確認對話框 
    Sheets.Add after:=Sheets(Sheets.Count) 
    Sheets(Sheets.Count - 1).Delete 
    Application.DisplayAlerts = True    '開啓確認對話框  End Sub 
2) 隱藏與顯示 
使用工作表的 visible屬性來設置工作表是否隱藏或顯示  隱藏  Sheets ("sheet2").Visible = False  顯示  Sheets ("sheet2").Visible =True 
3)保護與撤銷 
保護工作表使其不至被修改。 
Sheets(“工作表名 ”).Protect (Password)  
撤銷工作表保護使其被修改。 
 

Sheets(“工作表名 ”).Unprotect (Password)  
Password   Variant 類型,可選。爲一個字符串,該字符串爲工作表或工作簿指定區分大小寫的密碼。如 果省略本參數,不用密碼就可以取消對該工作表或工作簿的保護。否則,必須指定密碼,通過密碼來取消 對該工作表或工作簿的保護。 
示例: Sheets(“sheet1”).Protect “123456”  Sheets(“sheet1”).Unprotect “123456” 
如果要對工作進行詳細保護設置,可參考Excel VBA參考,這裏僅講簡單的參數設置。 
第三節 單元格和區域操作 
Excel數據的計算歸根到底還是對錶的單元進行的,所以單元格和區域操作非常重要的,這一節就詳
細介紹這方面的內容。 
一、如何引用單元格和區域   
1)用 Range屬性引用單元格和單元格區域  使用  Range 屬性來引用  A1 引用樣式中的單元格或單元格區域及進行屬性更改和賦值。如例句:  Sheets("Sheet1").Range("A1:D5").Font.Bold = True   
Sheets("Sheet1").Range("A1:D5").Value = 10000 
Range 對象既可表單個單元格,也可表單元格區域。下面說明 Range 對象最常用方法。 
引用                    含義    Range("A1")            單元格  A1  
Range("A1:B5")         從單元格  A1 到單元格 B5 的區域   
Range("C5:D9,G9:H16")  多塊選定區域   
Range("A:A")           A 列  
Range("1:1")            第一行  
Range("1:5")            從第一行到第五行的區域  
Range("1:1,3:3,8:8")      第  1、 3 和  8 行  
Range("A:C")           從  A 列到 C 列的區域   
Range("A:A,C:C,F:F")    A 、 C 和  F 列  
Range("單元格區域名礀 ")   命名的單元格區域   
2)用 Cells屬性引用單元格 
可用 Cells 屬性通過行列編號來引用單個單元格。下例中 Cells(6,1) 返回 Sheet1 上的單元格 A6,然後將  Value 屬性設置爲 10。如:Worksheets("Sheet1").Cells(6, 1).Value = 10  因爲可用變量替代行列編號,所以 Cells 屬性非常適合單元格區域中循環且速度很快。如下例所示:   Sub CC ()      Dim Counter As Integer      For Counter = 1 To 20          Worksheets("Sheet1").Cells(Counter, 3).Value = Counter      Next Counter  End Sub 
3)用 Rows或Columns屬性引用行列 
可用 Rows 屬性或 Columns 屬性來處理整行或整列。下例中,用 Rows(1) 返回 Sheet1 上的第一行,然
 

後將單元格區域的 Font 對象的  Bold 屬性設置爲 True。如:Worksheets("Sheet1").Rows(1).Font.Bold = True 
下表舉例說明了使用  Rows 和  Columns 屬性的一些行和列的引用。  引用               含義    Rows(1)           第一行  
Rows             工作表上所有的行  
Columns(1)        第一列  
Columns("A")      第一列  
Columns          工作表上所有的列  
4)用 Union方法合併區域後引用 
若要同時處理若干行或列及區域,請創建一個對象變量並使用  Union 方法,將對多個區域組合起來。下 例將活動工作簿中第一張工作表上的第一行、第三行和第五行的字體設置爲加粗。  Sub SeveralRows()      Worksheets("Sheet1").Activate      Dim myUnion As Range      Set myUnion = Union( Rows(1), Rows(3), Rows(5))      myUnion.Font.Bold = True  End Sub 
5)用括號 [ ]引用單元格和區域 
可用方括號將 A1 引用樣式或命名區域括起來,作爲  Range 屬性的快捷方式。這樣就不必鍵入單詞 “ Range”或使用引號,如下例所示:Worksheets("Sheet1").[A1:B5].ClearContents  [MyRange].Value = 30 
6) 用 Offset相對其他單元格來引用單元格  
處理相對於另一個單元格的某一單元格的常用方法是使用   Offset 屬性。下例中,將位於活動工作表上活 動單元格下一行和右邊三列的單元格的內容設置爲雙下劃線格式。  如:ActiveCell.Offset(1, 3).Font.Underline = xlDouble 
7) 用 Selection 屬性引用活動區域 
Select 方法激活工作表和工作表上的對象;而  Selection 屬性返回代表活動工作簿中活動工作表上的當前 選定區域的對象。在成功使用  Selection 屬性之前,必須先激活工作簿,並激活或選定工作表,然後用  Select  方法選定單元格區域(或其他對象)。 
宏錄製器經常創建使用  Select 方法和 Selection 屬性的宏。下輀  Sub 過程是用宏錄製器創建的,該過程 演示了  Select 方法和 Selection 屬性在一起使用的方法。 
Sub Macro1() 
    Sheets("Sheet1").Select 
    Range("A1").Select 
    ActiveCell.FormulaR1C1 = "Name" 
    Range("B1").Select 
    ActiveCell.FormulaR1C1 = "Address" 
    Range("A1:B1").Select 
    Selection.Font.Bold = True 
 

End Sub 
8)區域中循環引用單元格方法 
使用 VBA時,經常需要對某一單元格區域內的每個單元格運行同一段語句。爲達到這一目的,可組
合循環語句和一個或多個方法來標識每個單元格,一次針對一個單元格,並執行該操作。  
8.1) For...Next 循環語句與  Cells 屬性配合使用 
使用  Cells 屬性時,可用循環計數器(或其他變量或表達式)來替代單元格索引編號。下例中變量  
counter 代替行號。此過程在單元格區域  C1:C20 中循環,將絕對值小於 0.01的單元都置爲  0。 
Sub RoundToZero1()      For Counter = 1 To 20 
       If Abs(Cells(counter,3).value) < 0.01 Then Cells(counter,3) = 0 
    Next  End Sub 
8.2) For Each...Next 循環語句和 Range 屬性配合使用  示例如下:  Sub RoundToZero2()      For Each c In Worksheet s("Sheet1").Range("A1:D10").Cells          If Abs(c.Value) < 0.01 Then c.Value = 0      Next  End Sub 
二、如何處理單元格和區域    1 處理三維區域    如果要處理若干工作表上相同位置的單元格區域,可用   Array 函數選定兩張或多張工作表。下例設置三 維單元格區域的邊框格式。  Sub FormatSheets()      Sheets (Array("Sheet2",  "Sheet3", "Sheet5")).Select      Range("A1:H1").Select      Selection.Borders(xlBottom).LineStyle = xlDouble  End Sub 
2 處理活動單元格   
ActiveCell 屬性返回代表活動單元格的  Range 對象。可對活動單元格應用  Range 對象的任何屬性和方 法,如下例所示。 
Sub SetValue() 
    Worksheets("Sheet1").Activate 
    ActiveCell.Value = 35  End Sub  注意    只有活動單元格所在的工作表處於活動狀態時,才能處理該活動單元格。  
3 選擇活動單元格周圍的單元格 
CurrentRegion 屬性返回由空白行和空白列所包圍的單元格區域。下例中,選定區域擴充到與活動單元格
 

相鄰的包含數據的單元格中,然後用“貨幣”樣式設置該區域的格式。   Sub Region()      Worksheets("Sheet1").Activate      ActiveCell.CurrentRegion.Select      Selection.Style = "Currency"  End Sub 
4 單元格和區域賦值 
用賦值號 = 賦值,如給 A1賦值爲 10:Range(A1).Value=10 (由於 Value是默認屬性,所以可以直接省略 )  區域賦值,如 Range(A1:D5)=10 
5 單元格和區域賦予公式進行計算 
把公式字符串賦予給單元格或區域的 Formula屬性,如下例 : 注意一點是公式字符串中要有開頭的等號=。  Sub EnterFormula()      Worksheets("Sheet1").Range("D6").Formula = "=SUM(D2:D5)"  End Sub 
三、單元格和區域的定位 
1) 使用單元格的 End屬性來定位邊界  如:  數據區域的最下行的確定:  Sheets(1).cells( 65536,1).End(xlup).Row  數據區域的最右列的確定:  Sheets(1).cells(1,1).End(xltoright).Column  選定包含單元格“ B4”的區域在  B 列中頂端的單元格: Range("B4").End(xlUp).Select  選定包含單元格“ B4”的區域在第  4 行中最右端的單元格: Range("B4").End(xlToRight).Select  將選定區域從單元格“ B4”延伸至第四行最後一個包含數據的單元格 :   Range("B4", Range("B4").End (xlToRight)).Select 
2) 善用已用區域UsedRange對象來獲得區域範圍  如:需要獲得先前表格已用區域的最右下角單元格位置  Sub Loc () 
temp = [a1] :[a1] = 1                     ‘ 使用 A1單元格,保證已用區域從 A1開始    irow = ActiveSheet.UsedRange.Rows.Count    ‘右下單元格行  icol = ActiveSheet.UsedRange.Columns.Count  ‘右下單元格列  [a1] = temp                               ‘ 還原 A1的值  Cells(irow, icol).Select                      ‘ 選中右下角單元格 
End sub 
四、單元格和區域的保護與鎖定  
1)工作表選擇改變事件過程中保護,如下:不許可用戶選擇及改動保護單元格區域,示例中保護 B1:B10  Private Sub Worksheet_SelectionChange(ByVal Target As Range)      Dim rng As Range      Set rng = Range("b1:b10")      If Intersect(Target, rng) Is Nothing Then Exit Sub    ‘ 選擇單元不在保護區內就退出       MsgBox "不可以選取單元格!" & Target.Address  ‘選擇單元在保護區內就改變選擇       ActiveSheet.Range("a1").Select  End Sub 
 

2)通過行列的隱藏來保護 
本示例隱藏工作表“ Sheet1”的第5行和C列  Sub SetHide() 
With Worksheets("Sheet1")             ‘ 使用With …End With語句塊,提高效率  .Unprotect                           ‘ 撤銷保護,如果原先未保護則不需該句  .Rows(5).Hidden = True                ‘ 隱藏第5行  .Columns("C").Hidden = True           ‘ 隱藏C列  .Protect                             ‘ 啓動保護,如果原先未保護則不需該句  End with 
End Sub 
3)通過鎖定區域來保護,可限定未鎖定區域內輸入   Sub SetLock()      ActiveSheet.Unprotect      Cells.Locked = True                  ‘ 鎖定全表 
   Range("a1:b10").Locked =false        ‘ 解鎖區域 A1:B10,限定該區域爲可輸入區 
    ActiveSheet.Protect  End Sub 
第四節 圖表的操作 
Excel讓人喜愛的原因就是它有強大得計算功能和數圖相關聯的數據作圖功能。本節就介紹下 VBA代 碼作圖方面內容。通過代碼作重複的圖,可以大大提高效率,比如我的作品 GeoPlot(www.geoplot.net)。 Excel圖的代碼繪製,最好是學習錄製的宏來分析 VBA代碼的作用,最後優化而成通用程序塊。 
一.新建及類型 
1)設置一個對象等於新增圖表對象就建立好了一個新圖 
1.1) 新圖賦值給對象變量 
Set mychart = Sheets(1).ChartObjects.Add (ChrLeft, ChrTop, ChrWidth, ChrHeight) 
說明:增加一個嵌入圖表,其左上角的位置座標爲( ChrLeft, ChrTop),長寬爲 ChrWidth×ChrHeight, 單位爲磅。1磅爲 1/72 英寸和 0.035 釐米,字體大小通常用磅數量度。  1.2) 直接增加一個圖對象到圖對象集Charts 
 Charts.A dd
2)圖的類型可以更改 Chart對象的屬性 ChartType來實現 
2.1)圖表對象變量的使用 
mychart.Chart.ChartType = xlXYScatterLines              ' 散點圖折線類型 
2.2)未設置對象變量的圖 
它的類型更改需要在增加它後,連續操作讓它處於激活狀態( ActiveChart),這樣可通過當前活動
圖ActiveChart來使用。如:ActiveChart.ChartType = xlPie    ‘餅圖 
3)圖表有兩大類,一是嵌入工作表上的圖,另一類是作爲新工作表圖,其設置如下: 
3.1)嵌入工作表上的圖 
ActiveChart.Location Where:=xlLocationAsObject, Name:= "Sheet1" 或如1.1生成新圖時就定義爲
生成嵌入圖ChartObjects.Add 
 

3.2)新工作表圖 
ActiveChart.Location Where:=xlLocationAsNewSheet 或用圖表對象變量屬性更改  mychart.location 
where:= xlLocationAsNewSheet 
二.設置圖表的數據 
一般是使用 Excel表格上數據,所以可以通過設置 Chart圖表對象的數據來源屬性來獲得作圖需要的
數據。如:ActiveChart.SetSource Date Source:=Sheets("Sheet1").Range("A1:B6"), PlotBy:= xlColumns  這裏的 PlotBy:= xlColumns表示按列繪製數據;也可以按行繪製,其參數爲PlotBy:= xlRows。 
另外一種數據設置是對圖的橫、縱座標數據分別賦值。如: 
        mychart.chart.SeriesCollection.NewSeries                     ‘ 增加一個系列數據 
        mychart.chart.SeriesCollection(1).XValues = Array(45, 100)       ‘ 橫座標數據組或單元對象 
        mychart.chart.SeriesCollection(1).Values = Array(50, 180)        ‘ 縱座標數據組或單元對象 
三.圖表格式設置 
對於圖的格式設置,一般是錄製一個宏,再刪除不需要的語句,這樣是開發者最省事的方法。在本節
的示例中有詳細的格式設置,可以更改座標軸的名礀,大小範圍,刻度大小等。對不清楚的圖的類型名礀, 格式參數,我們都可以通過錄制宏來了解學習。時刻記住,錄製宏來分析代碼,是最好的學習方法。  
四.散點圖增加一個系列和增加文字標籤 
1)用圖表的系列集合對象的方法 NewSeries,就可以增加圖的系列,然後再對新系列進行設置,如下: 
mychart.chart.SeriesCollection.NewSeries                     ‘ 增加一個系列數據  mychart.chart.SeriesCollection(1).XValues = Array(45, 100)       ‘橫座標數據組或單元對象  mychart.chart.SeriesCollection(1).Values = Array(50, 180)        ‘ 縱座標數據組或單元對象 
     2)對於散點圖,我們可以增加文字標籤於圖上,方法如下:增加一個新的系列,不過數據就一點,不顯 示數據點,而僅顯示它的數據標籤即可。如下示例。          With mychart.chart.SeriesCollection(2)           .MarkerStyle = xlNone                             ' 不顯示點標記           .Points(1).HasDataLabel = True                      ' 數據標記及顯示文字標籤           .Points(1).DataLabel.Text =”標籤文字”               ' 標籤文字           .DataLabels.Position = xlLabelPositionCenter           ' 位置風格,居中 
End With 
五.實例 
1) 生成一個散點嵌入圖於工作表窗口中心,繪製一條直線(45,50)— (100,180), 在第一點顯示文字標籤  
“Test”,此外還加一個點( 80, 100)。 
代碼和詳細註釋如下: 
Sub DrawChart() 
'*******************************圖表對象的定義和生成***********************************      '定義對象變量,以便設置它爲圖表( chart)對象及圖位置大小變量 
    Dim mychart As Object, mysheet As Object 
 Dim ChrLeft As Long, ChrTop As Long, ChrWidth As Long, ChrHeight As Long 
     
    On Error Resume Next 
    Application.ScreenUpdating = False 
 

 ChrWidth = 250: ChrHeight = 250 
 ChrLeft = Abs(Windows(ThisWorkbook.Name).Width - ChrWidth) / 2 
    ChrTop = Abs(Windows(ThisWorkbook.Name).Height - ChrHeight) / 2  ' 計算圖表在窗口中心座標 
    Set mychart = Sheets(1).ChartObjects. Add(ChrLeft, ChrTop, ChrWidth, ChrHeight) 
  
   With mychart.Chart 
        .ChartType = xlXYScatterLines                           ' 散點折線圖類型 
        .SeriesCollection.NewSeries                              ' 增加一次投點,畫條直線 
        .SeriesCollection(1).XValues = Array(45, 100) 
        .SeriesCollection(1).Values = Array(50, 180) 
        .SeriesCollection(1).Points(1).HasDataLabel = True            ' 點1是否顯示數據標籤 
        .SeriesCollection(1).Points(1).DataLabel.Text = "Test"          ' 點1的標籤文字 
        .SeriesCollection.NewSeries                               ' 增加一次投點,就投個點( 80,100) 
        .SeriesCollection(2).XValues = 80 
        .SeriesCollection(2).Values = 100 
    End With  '*******************************圖表風格定義***********************************      With mychart.Chart 
        .ChartArea.Font.Size = 10                                    ' 圖表字符的大小 
        .HasLegend = False                                         ' 圖是否顯示圖例 
        .Axes(xlCategory, xlPrimary).HasTitle = True                    'X 軸是否有座標名 
        .Axes(xlCategory, xlPr imary).AxisTitle.Characters.Text = "X" 
        .Axes(xlValue, xlPrimary).HasTitle = True 
        .Axes(xlValue, xlPrim ary).AxisTitle.Characters.Text = "Y" 'Y軸座標名"Y" 
        .PlotArea.Interior.ColorIndex = xlNone                         ' 定義投圖區爲透明 
    End With 
     
With mychart.Chart.Axes(xlCategory) 
        .MinimumScale = 0                                         ' 定義X座標軸最小值 
        .MaximumScale = 200                                       ' 定義X座標軸最大值 
        .MinorUnit = 10                                            ' 定義次刻度線單位 
        .MajorUnit = 50                                           ' 定義主刻度線單位 
        .CrossesAt = 0                                            'X 軸交匯點設爲0 
        .MajorTickMark = xlInside                                  ' 主刻度線方向朝內 
        .MinorTickMark = xlInside                                  ' 次刻度線方向朝內 
        .HasMajorGridlines = False                                  ' 是否顯示主網格線 
        .HasMinorGridlines = False                                  ' 是否顯示次網格線 
   End With 
    
   With mychart.Chart.Axes(xlValue) 
        .MinimumScale = 0                                         ' 定義y座標軸最小值 
        .MaximumScale = 200                                       ' 定義y座標軸最大值 
        .MinorUnit = 10                                            ' 定義次刻度線單位 
        .MajorUnit = 50                                             ' 定義主刻度線單位 
        .CrossesAt = 0                                              'Y 軸交匯點設爲0 
 

        .MajorTickMark = xlInside                                    ' 主刻度線方向朝內 
        .MinorTickMark = xlInside                                    ' 次刻度線方向朝內 
        .HasMajorGridlines = False                                    ' 是否顯示主網格線 
        .HasMinorGridlines = False                                    ' 是否顯示次網格線 
   End With 
     
    Set mychart = Nothing                                             ' 刪除圖表對象變量 
    Application.ScreenUpdating = True                                   ' 恢復屏幕刷新  End Sub 
2)根據工作表一的 A1:B10數據生成柱狀圖嵌入表一,位置爲數據右下角位置。 
Sub Pic2()      On Error Resume Next 
    Application.ScreenUpdating = False 
    Charts.Add 
    ActiveChart.ChartType = xlColumnClustered 
    ActiveChart.SetSourceDat a Source:=Sheets("Sheet1").Range("A1:B10"), PlotBy:=xlColumns 
    ActiveChart.Location Where:=xlLocationAsObject, Name:="Sheet1" 
    ActiveSheet.Shapes(ActiveSheet.Shapes.C ount).Left = ActiveSheet.Cells(11, 3).Left    '定位於單元格
(10,2)右下角 
    ActiveSheet.Shapes(ActiveSheet.Shape s.Count).Top = ActiveSheet.Cells(11, 3).Top 
    Application.ScreenUpdating = True  End Sub 
第三章  Excel VBA高級使用 
通過以上章節的學習,估計大家都夠能使用 Excel VBA進行基本的數據計算、數據彙總、數據的保存、 數據庫的使用和繪製圖表了,這些功能已經可以解決我們平時所遇到的大多數問題。但有時還會遇到一些 較難的問題,如計算機硬件或底層方面的使用。這些問題可以使用本章介紹的Windows API來解決。 
Windows API是Windows的 32位應用程序編程接口,是一系列複雜函數、消息和結構的集合。這種
集合被包含在一個後綴名爲 DLL的動態連接庫文件中,裝有Windows系統的電腦都有標準的Windows動 態連接庫文件。編程人員可用不同編程語言的引用方法來使用它們,進而編制出解決 Windows系統底層問 題的應用程序。Excel VBA中使用 API可以讓我們輕鬆實現一些高級功能,比如多媒體播放等,所以有必 要了解一些 API在 Excel VBA中的使用。一般來講,只有會了Windows API纔算真正進入了Windows系 統下程序開發的大門。 
第一節  Win API的使用 
    Windows API 是英文Application Programming Interface的縮寫,Win32 API也就是微軟Windows 32位 操作系統的應用程序編程接口。我們可以認爲 API函數是構築整個Windows框架的基石,在它的下面是 Windows的操作系統核心,而它上面則是Windows的應用程序。在 Excel VBA中使用 API就是爲了開發 出實用高效的應用程序,而 VBA下使用 API函數需進行API函數的堀明才能使用。   一、堀明 API函數      堀明 VBA所在文件之外的過程或函數就能夠訪問 Windows API或其它外部動態連接庫( DLL)。在堀 明瞭過程或函數後,其調用方法與 VBA自己的過程或函數調用方法相同。要堀明一個 DLL文件中的過程
 

或函數,需要在代碼窗口增加一個 Declare語句。例如取的計算機名礀的函數  GetComputerName ,作如 下堀明: 
Private Declare Function GetComputerName Lib "kernel 32" Alias "GetComputerNameA" (ByVal lpBuffer As 
String, nSize As Long) As Long  或  Public Declare Function GetComputerName Lib "kernel 32" Alias "GetComputerNameA" (ByVal lpBuffer As 
String, nSize As Long) As Long 
    以上堀明的不同在於所堀明函數的使用範圍, Private Declare堀明的是模塊私有,只能在堀明它的模 塊內調用; Public Declare堀明的是全局函數,可以在應用程序的任何地方調用,一般我們使用 Public Declare 堀明。堀明完畢後就能在程序中使用此函數。  
二、使用 API函數或過程 
    以 API函數 Beep來說明 API函數的幾種使用方法, Beep函數的介紹如下:  【 VBA堀明】  Public Declare Function Beep Lib "kernel32" Alias "Beep" (ByVal dwFreq As Long, ByVal dwDuration As 
Long) As Long  【說明】    用於生成簡單的堀音   【返回值】    Long,非零表示成功,否則返回零。  【參數表】    dwFreq ---------  Long,堀音頻率(從 37Hz到32767Hz)。    dwDuration -----  Long,堀音的持續時間,以毫秒爲單位。如爲 -1,表示一直播放堀音,直到再次調用 該函數爲止。 
   可採用以下幾種方式使用API函數或過程,以 Beep爲例:  (1)忽略函數返回值的調用:       Beep 1000, 5000 
注意此時函數的參數是不加括號的。  
(2) Call方法調用:       Call Beep(1000, 5000) 
注意這裏需要加上括號,但我們不取回函數的返回值。 
(3)取得函數返回值的調用:          MyLng = Beep(1000, 5000)  
此時需要加上括號,而且我們必須事先定義一個變量(變量的類型與函數返回值類型相同)來存儲
API函數的返回值。
三、堀明的一些說明 
(1)堀明中的 Lib 和  Alias 是怎麼回事     一般情況下Win32 API函數總是包含在Windows系統自帶的或是其它公司提供的動態連接庫 DLL中, 而 Declare語句中的關鍵字Lib就是用來指定 DLL(動態連接庫)文件路徑是系統庫路徑的,這樣 VBA才 能找到這個 DLL文件,然後才能使用其中的 API函數。     如果我們只是列出 DLL文件名而不指出其完整路徑的話, VBA會自動到 Excel文件所在目錄、當前工 作目錄、Windows/System目錄、Windows目錄下搜尋這個 DLL文件。所以如果所要使用的 DLL文件不在
 

上輀幾個目錄下的話,我們應該指明其完整路徑。  
   Alias用於指定 API函數的別名,如果我們調用的 API函數要使用字符串(參數中包含 String型)的話, Alias關鍵字是必須的。這是因爲在 ANSI和 Unicode字符集中同一API函數的名礀可能不一樣,爲了保證 不出現堀明錯誤,所以我們使用 Alias關鍵字指出API函數的別名。   
(2)常見API參數類型的說明 
   API函數的參數中最常見的是長整型數據( Long)類型,例如 API中的句柄、一些特定的常量、函數 的返回值都是此類型的值;另外幾種常見的參數類型有:整型Integer、 Byte型、String型等。 
(3)堀明中的 ByVal是作什麼用的 
   這跟 VBA的參數傳遞方式有關,在默認情況下 VBA是通過傳值方式傳遞函數的參數、而有些 API函 數要求必須採用地址傳遞方式(ByRef)來傳遞函數參數(這兩種參數傳遞方式是不同的,前者傳遞的是 參數真實的值,而後者要求是一個地址指針)。堀明中的  ByVal 表明參數是傳遞一個值。 
(4)怎樣輕鬆得到完整API函數堀明 
   Visual Basic 6.0 自帶 API文本查看器 API Text Viewer,我們可以使用它來找到 API函數的完整堀明, 然後把它粘貼到程序就可使用。如果未安裝VB6,大家可以到網上下載,此外網絡上還有很多 API函數的 介紹,大家也可以下載來學習。     大家使用 API有必要對它進行有一定了解,然後再去使用 API文本查看器。雖然不必刻意研究每個 API 函數(如果真的知道 100來個 API函數的使用,相信絕對有用),但是需要我們瞭解一下該函數的作用。 而對 API函數功能的介紹,網絡也有現成的軟件供大家下載使用。 
四、示例 
(1)彈出一個對話框,提示計算機的名礀,並且揚堀器喇叭會鳴叫。 
Private Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As 
Long 
Private Const MAX_COMPUTERNAME_LENGTH As Long = 31 
Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer 
As String, nSize As Long) As Long 
Sub ComputerName()      Dim dwLen As Long 
    Dim strString As String 
    '創建緩衝區 32位 
    dwLen = MAX_COMPUTERNAME_LENGTH + 1 
    strString = String(dwLen, "X") 
    '獲得計算機名礀 
    GetComputerName strString, dwLen 
    '獲得實際名礀字串 
    strString = Left(strString, dwLen) 
    '播放頻率爲 4500赫茲的揚堀器堀音,持續 100微秒 
    For I = 0 To 5 
        Beep 4500, 100 
        DoEvents 
    Next 
    '顯示計算機名礀 
 

    MsgBox "電腦名礀是  " & strString & ", 我搞對了嗎? "  End Sub 
(2) API函數 ShellExecute的使用,打開網頁和發送郵件。   API函數 ShellExecute的介紹:  【 VBA堀明】 
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, 
ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As 
String, ByVal nShowCmd As Long) As Long  【別名】    ShellExecuteA  【說明】    查找與指定文件關聯在一起的程序的文件名    【返回值】    Long,非零表示成功,零表示失敗。    【參數表】    hwnd -----------  Long,指定一個窗口的句柄,有時候,windows程序有必要在創建自己的主窗口前 顯示一個消息框    lpOperation ----  String,指定字串“ open”來打開 lpFlie文檔,或指定“ Print”來打印它    lpFile ---------  String,想用關聯程序打印或打開一個程序名或文件名    lpParameters ---  String,如 lpszFlie是可執行文件,則這個字串包含傳遞給執行程序的參數    lpDirectory ----  String,想使用的完整路徑    nShowCmd -------  Long,定義瞭如何顯示啓動程序的常數值。參考ShowWindow函數的 nCmdShow 參數  示例代碼: 
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _ 
 (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _ 
 ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long 
Private Const SW_SHOWNORMAL As Long = 1 
Private Sub CommandButton1_Click()      Unload Me  End Sub 
Private Sub Label4_Click()      '啓動郵件程序 
 ShellExecute 0, "Open", "mailto:[email protected]", "", "", SW_SHOWNORMAL 
    Unload Me  End Sub 
Private Sub Label5_Click() 
    '啓動網絡程序, 連接到Excelhome論壇的帖子上  ShellExecute 0, "Open",    _  "http://club.excelhome.net/dispbbs.asp?boardid=2&replyid=462739&id=178278&page=1&skin=0&Star=1",  "", "", SW_SHOWNORMAL 
 

    Unload Me  End Sub 
第二節  Excel VBA程序的保密 
Excel VBA 程序的保密是個難點,大家對此都感興趣,原因是想保護核心代碼和技術以及對商業的
Excel VBA 程序進行安全保障。Excel 對  VBA 工程加密僅起簡單保護作用,稍懂一點的程序員就可手工 破解或使用網上的破解軟件。目前唯一能保障  VBA 代碼就一個方法,把 VBA 核心代碼封裝到動態連接 庫( DLL)文件中。大家可以放心動態連接庫,因爲它是很難被反編譯的(反編譯的代價比開發還大) 、 非常安全。下面就開始介紹如何製作和使用動態連接庫 DLL。 
一、動態連接庫 DLL的製作和使用 
1)用 VB6 企業版下 ActiveX.DLL 工具開發,在缺省類代碼窗口輸入下面代碼:  
 Sub copy12(x As Integer, y As Integer)            ' 目的是把表x單元格值賦值給表 y     '定義將要用到的變量數據,對象變量,整型數據變量 
 Dim xlapp As Object, xlbok As Object,xlsht1 As Object,xlsht2 As Object, xlrng As Object 
 Dim i As Integer, j As Integer, irow1 As Integer, icol1 As Integer 
 Dim irow2 As Integer, icol2 As Integer, cellssum As Integer 
    Set xlapp = GetObject(, "Excel.Application")  '取得 Excel實例 
    Set xlbok = xlapp.activeworkbook           ' 取得 Excel實例下活動工作簿 
    Set xlsht1 = xlbok.Worksheets(x)            ' 取得 Excel實例下活動工作簿的第 x表格 
    Set xlsht2 = xlbok.Worksheets(y)            ' 取得 Excel實例下活動工作簿的第 y表格 
    Set xlrng = xlsht1.UsedRange              ' 取得 Excel實例下活動工作簿的第x表格的已用區域 
    cellssum = xlrng.Count                     'x 表格的已用區域的單元格數目 
    irow1 = xlrng.cells(1).row                   ' 已用區域的第1單元格的行 
    icol1 = xlrng.cells(1).Column                ' 已用區域的第1單元格的列 
    irow2 = xlrng.cells(cellssum).row             ' 已用區域的最後單元格的行 
    icol2 = xlrng.cells(cellssum).Column          ' 已用區域的最後單元格的列 
     
    For i = irow1 To irow2                      ' 從已用區域第1行到最後一行循環 
       For j = icol1 To icol2                    ' 從已用區域第1列到最後一列循環 
          xlsht2.cells(i, j) = xlsht1.cells(i, j)       ' 把x表已用區域單元格數據賦值給y表相同位置 
       Next                                 ' 此處目的可用別方法實現,或加判斷實現別的 
    Next 
    Set xlapp = Nothing                        ' 清除定義的對象爲空 
    Set xlbok = Nothing 
    Set xlsht1 = Nothing 
    Set xlsht2 = Nothing 
    Set xlrng = Nothing  End Sub 
Function Getstrgs(STRG As String, FC As String, LC As String) As Variant      '求字符間各子串賦值給數組      Dim ss() As String      On Error Resume Next 
 

    Sum = 0 
 For i = 1 To Len(STRG) - 1 
        If Mid(STRG, i, 1) = FC Then 
            For j = i + 1 To Len(STRG) 
                If Mid(STRG, j, 1) = LC Then Sum = Sum + 1 
            Next 
        End If 
    Next 
    If Sum < 1 Then 
        MsgBox "No substring found!" 
        Exit Function 
    End If 
    ReDim ss(Sum - 1) As String 
    Sum = 0 
 For i = 1 To Len(STRG) - 1 
        If Mid(STRG, i, 1) = FC Then 
            For j = i + 1 To Len(STRG) 
                If Mid(STRG, j, 1) = LC Then 
                    ss(Sum) = Mid(STRG, i + 1, j - i - 1) 
                    Sum = Sum + 1 
                End If 
            Next  
        End If 
    Next 
    Getstrgs = ss  End Function 
以上代碼僅展示類中的過程和函數,以便在 VBA中使用。 
2)修改將要引用的類名礀,在 VB6的類屬性窗口修改,本例修改爲  mycopy1to2 
3)工程保存,本例保存爲 sheetcopy1to2 
4) DLL生成,本例保存爲sheetcopy1to2.dll       2-4步驟對大家來說,不應該存在問題的。 
二. VBA中調用 DLL 
1) VBE窗口下,點工具菜單-引用,在點彈出窗口的瀏覽按鈕,找到你的 DLL文件,最好和 EXCEL
文件放一個目錄下,便於下一步驟。 
2) DLL的註冊,如下: 
Private Sub Workbook_BeforeClose(Cancel As Boolean) 
 Shell "Regsvr32 /u /s " & Chr(34) & ThisWorkbook.Path & "/sheetcopy1to2.dll" & Chr(34) 
End Sub 
Private Sub Workbook_Open() 
  '一定要先引用  dll,纔可以自動註冊."Regsvr32 /s " 中/s是表示不出現對話框 
 

 On Error GoTo errline 
 Shell "Regsvr32 /s " & Chr(34) & ThisWo rkbook.Path & "/sheetcopy1to2.dll" & Chr(34) 
  Exit Sub  errline:    MsgBox "程序在註冊DLL函數時出現錯誤! "  End Sub 
也可以在Windows 開始菜單下的運行命令對話框中運行 Regsvr32 "DLL全路徑/文件名 .dll" 來註冊
DLL文件 
3) VBA中使用 DLL的過程和函數,代碼示例如下   VBE下新建如下模塊: 
Sub mycopy1to2() 
 Dim bb As New mycopy1to2        ' 定義 bb爲 DLL中的類mycopy1to2   bb.copy12 1, 2                    ' 表格1內容到表格2,使用類mycopy1to2新實例 bb的過程 
 Set bb = Nothing  End Sub 
Sub mycopy2to3() 
 Dim bb As New mycopy1to2   bb.copy12 2, 3                    ' 表格2內容到表格 3 
 Set bb = Nothing  End Sub 
Sub mycopy3to1() 
 Dim bb As New mycopy1to2   bb.copy12 3, 1 
 Set bb = Nothing  End Sub 
Sub string1() 
 Dim aa As Variant 
 Dim bb As New mycopy1to2                  ' 定義 bb爲 DLL中類 mycopy1to2 新實例   aa = bb.Getstrgs(Cells(1, 1), Cells(1, 2), Cells(1, 3))       '使用類mycopy1to2新實例 bb的函數 
 For i = 0 To UBound(aa)                              '用 DLL中類的函數求字符串的各子串 
 Cells(i + 2, 1) = aa(i) 
Next 
 Set bb = Nothing  End Sub 
代碼能理解多少就多少,這是次要的,主要是學會如何輕鬆使用 DLL保護自己的 VBA代碼。學到這,
相信大家應該已經會製作 DLL文件和在 VBA中使用它了。 
2) 獲得硬盤物理地址 
 

爲什麼要獲得物理地址,那是因爲電腦上唯一不變的就是硬盤物理地址號碼。比如網卡的物理地址, 大家都會改動。因此獲得該硬盤物理地址號碼用來加密和註冊,便顯得非常之重要。其獲得地址的代碼如 示例,由於其較長,所以這裏就省略。實際使用時,把該代碼和註冊加密的代碼封裝到 DLL庫中使用。 
3) 加密與註冊 
    對正版軟件的註冊,有效的方法是一機一碼,即一勻電腦一個註冊碼。即使別人獲得了註冊碼和軟
件,在別的機子上也無法使用。這一機一碼就是基於電腦硬盤的唯一物理地址。打個比方來理解這個方法: 電腦上的硬盤物理地址爲 DISK_ID,經過鑰匙串 KEY1加密得到User_ID;軟件開發人員然後根據鑰匙串 KEY1解密User_ID獲得用戶的 DISK_ID,再經鑰匙串 KEY2加密獲得所謂的註冊號Reg_ID;用戶輸入
Reg_ID並存在電腦註冊表或文件上,軟件啓動後,調用註冊覈對功能,通過 KEY2加密 DISK_ID獲得一 字符串,與 REG_ID對比,看是否一致,不一致則提示未註冊並關閉程序運行。這裏的KEY1和 KEY2及 加密解密算法,都存放在 DLL中,核心程序也存放在該DLL中,所以該方法註冊可以保證一機一碼且安 全。下面就介紹多種字符串加密解密算法的一種,是我以前看啥資料想到後設計出的。 
基礎原理如下: 
A. 可見字符的ASC碼:0-9的 Asc碼爲 48-57;大寫A-Z的 Asc碼爲 65-90;小寫a-z 的 Asc碼爲 97-122。
Asc碼是一整數型數據,佔一個字節8位長度。 
B. 異或操作(對應位的數字不同則爲 1,相同爲0):舉個例,電腦裏一個字節的二進制數: 01101110
與11000011異或結果爲10101101,該結果在與11000011再異或一次,其結果是 01101110,這與開始的數 相同,所以一個數對另一個數兩次異或就會復原。  
(1)加密步驟,PlainStr爲待加密字串, KEY爲鑰匙字串。 
第一步:取 KEY第一個字符的 Asc碼和 PlainStr每一個字符的 Asc碼異或,如果異或結果爲可見字符的
Asc碼範圍,則其 Asc碼對應的字符爲新加密字符,否則新加密字符就是剛纔的 PlainStr對應位置的字符, 各個加密字符合並就是被 KEY第一個字符的 Asc碼加密過的字符串,並取代 PlainStr。 
第二步:循環第一步,依次用 KEY的其餘字符按第一步方法執行,得到最後的PlainStr。 
第三步:異或操作後的 PlainStr長度爲偶數,則分爲左右兩半,左右兩字符串各自進行反序,其後合併
成一個字符串。 
第四步:經過以上三步的操作, PlainStr字符串就經過鑰匙字串 KEY的加密。 
(2)解密步驟,PlainStr爲待解密字串, KEY爲鑰匙字串。 
第一步:PlainStr長度爲偶數,則分爲左右兩半,左右兩字符串各自進行反序,其後合併成一個新的字
符串 PlainStr。 
第二步:取 KEY最後一個字符的 Asc碼和 PlainStr每一個字符的 Asc碼異或,如果異或結果爲可見字符
的 Asc碼範圍,則其 Asc碼對應的字符爲新解密字符,否則新解密字符就是剛纔的 PlainStr對應位置的字 符,各個解密字符合並就是被 KEY最後一個字符的 Asc碼解密過的字符串,並取代 PlainStr。 
第三步:循環第二步,依次用 KEY的其餘倒序字符按第二步方法執行,得到最後的PlainStr。 
第四步:經過以上三步的操作, PlainStr字符串就經過鑰匙字串 KEY的解密。 
示例代碼如下: 
'******************************************************************************  '                                     加密解密算法  '可見字符ASC碼: 48-57(0-9);65-90(A-Z);97-122(a-z)  '異或結果爲可見字符則異或  '偶數則把異或結果分成兩半各自並反序,增加破解難度 
 

'***********************************加密***************************************  Private Function Encrypt(PlainStr As String, key As String) as string 
Dim Char As String, KeyChar As String, NewStr As String, AscCode As Long 
Dim i As Integer, j As Integer, Side1 As String, Side2 As String 
For j = 1 To Len(key)                  '鑰匙字符串正向逐個取字符,用其 Asc碼和待加密字符串各字 符的 Asc碼異或操作 
    NewStr = "" 
    KeyChar = Mid(key, j, 1) 
    For i = 1 To Len(PlainStr)         ' 取待加密字符串各字符 
        Char = Mid(PlainStr, i, 1) 
        AscCode = Asc(Char) Xor Asc(KeyChar)   ' 對字符的 Asc碼異或操作 
 If (AscCode <= 57 And AscCode >= 48) Or (AscCode <= 90 And AscCode >= 65) Or (AscCode <= 
122 And AscCode >= 97) Then 
           NewStr = NewStr & Chr(AscCode)     ' 異或後的 Asc碼是可見字符的 Asc碼,則把異或結
果轉成字符,加入異或結果字符串 
        Else 
           NewStr = NewStr & Char             ' 異或後的 Asc碼是不可見字符的 Asc碼,則把原先
字符加入異或結果字符串 
        End If 
    Next i 
    PlainStr = NewStr  Next j 
If Len(PlainStr) Mod 2 = 0 Then                ' 異或結果字符串,其長度爲偶數則分左右兩半並各自反
序 
 Side1 = StrReverse(Left(PlainStr, (Len(PlainStr) / 2))) 
 Side2 = StrReverse(Right(PlainStr, (Len(PlainStr) / 2))) 
    PlainStr = Side1 & Side2                   ' 合併左右反序字符串  End If 
Encrypt = PlainStr                             ' 生成加密結果字符串 
End Function 
'***********************************解密***************************************  Private Function Decrypt(PlainStr As String, key As String) as string 
Dim Char As String, KeyChar As String, NewStr As String, AscCode As Long 
Dim i As Integer, j As Integer, Side1 As String, Side2 As String 
If Len(PlainStr) Mod 2 = 0 Then                ' 字符串爲偶數長度,則分左右兩半並各自反序 
 Side1 = StrReverse(Left(PlainStr, (Len(PlainStr) / 2))) 
 Side2 = StrReverse(Right(PlainStr, (Len(PlainStr) / 2))) 
    PlainStr = Side1 & Side2                   ' 合併左右反序後字符串  End If 
For j = Len(key) To 1 Step -1                  '反順序逐個取鑰匙字符串各字符,用其 Asc碼和待解密 字符串各字符的 Asc碼異或操作 
    NewStr = "" 
    KeyChar = Mid(key, j, 1)                    
 

    For i = 1 To Len(PlainStr)                 ' 對字符串每個字符的 Asc碼進行異或 
        Char = Mid(PlainStr, i, 1) 
        AscCode = Asc(Char) Xor Asc(KeyChar)   ' 字符的 Asc碼進行異或 
 If (AscCode <= 57 And AscCode >= 48) Or (AscCode <= 90 And AscCode >= 65) Or (AscCode <= 
122 And AscCode >= 97) Then 
           NewStr = NewStr & Chr(AscCode)     ' 異或後的 Asc碼是可見字符的 Asc碼,則把異或結
果轉成字符,加入異或結果字符串 
        Else 
           NewStr = NewStr & Char             ' 異或後的 Asc碼是不可見字符的 Asc碼,則把原先
字符加入異或結果字符串 
        End If 
    Next i 
    PlainStr = NewStr  Next j 
Decrypt = PlainStr 
End Function 
第四章  Excel VBA優化及結束語 
第一節  Excel VBA優化 
由於 Microsoft Office辦公套件的廣泛應用,以及該軟件版本的不斷提升,功能不斷完善,在 Office 辦公套件平勻上開發出的的 VBA應用程序越來越多,而 VBA是一種宏語言,在運行速度上有很大的限制。 因此 VBA編程的方法直接關係到VBA程序運行的效率,本節列舉了一些提高VBA程序運行效率的方法。  
方法1:儘量使用 VBA原有的屬性、方法和Worksheet函數   
由於 Excel對象多達百多個,對象的屬性、方法、事件多不勝數,對於初學者來說可能對它們不全部
瞭解,這就產生了編程者經常編寫與 Excel對象的屬性、方法相同功能的 VBA代碼段,而這些代碼段的運 行效率顯然與Excel對象的屬性、方法完成任務的速度相差甚大。例如用 Range的屬性 CurrentRegion來返 回Range 對象,該對象代表當前區。(當前區指以任意空白行及空白列的組合爲邊界的區域)。同樣功能的 VBA代碼需數十行。因此編程前應儘可能多地瞭解 Excel對象的屬性、方法。   
充分利用Worksheet函數是提高程序運行速度的極度有效的方法。如求平均工資的例子:      For Each c In Worksheet(1).Range(″A1:A1000″) 
   TotalV alue =TotalV alue+ c.Value 
   Next 
  AverageValue = TotalValue / Worksheet(1).Range(″A1:A1000″).Rows.Count 
而下面代碼程序比上面例子快得多: 
AverageValue=Application.WorksheetFunction.Average(Worksheets(1).Range(″A1:A1000″)) 
其它函數如 Count,Counta,Countif,Match,Lookup等等,都能代替相同功能的 VBA程序代碼,提高程序
的運行速度。   
方法2:儘量減少使用對象引用,尤其在循環中   
每一個 Excel對象的屬性、方法的調用都需要通過 OLE接口的一個或多個調用,這些OLE調用都是
需要時間的,減少使用對象引用能加快 VBA代碼的運行。例如   
 

1).使用With語句。 
  Workbooks(1).Sheets(1).Range(″A1:A1000″).Font.Name=″Pay″ 
    Workbooks(1).Sheets(1).Range(″A1:A1000″).Font.FontStyle=″Bold″ ...  則以下語句比上面的快 
With Workbooks(1).Sheets(1).Range(″A1:A1000″).Font 
    .Name = ″Pay″ 
    .FontStyle = ″Bold″ 
    ... 
   End With   
2).使用對象變量。 
如果你發現一個對象引用被多次使用,則你可以將此對象用 Set 設置爲對象變量,以減少對對象
的訪問。如: 
    Workbooks(1).Sheets(1).Range(″A1″).Value = 100 
    Workbooks(1).Sheets(1).Range(″A2″).Value = 200 
則以下代碼比上面的要快:  
   Set MySheet = Workbooks(1).Sheets(1) 
   MySheet.Range(″A1″).Value = 100 
   MySheet.Range(″A2″).Value = 200   
3).在循環中要儘量減少對象的訪問。     For k = 1 To 1000 
    Sheets(″Sheet1″).Select 
    Cells(k,1).Value = Cells(1,1).Value 
  Next k 
則以下代碼比上面的要快:
   Set TheValue = Cells(1,1).Value 
   Sheets(″Sheet1″).Select 
   For k = 1 To 1000 
    Cells(k,1).Value = TheValue 
  Next k   
方法3:減少對象的激活和選擇  
如果你的通過錄制宏來學習 VBA的,則你的 VBA程序裏一定充滿了對象的激活和選擇,例如
Workbooks(XXX).Activate、 Sheets(XXX).Select、 Range(XXX).Select等,但事實上大多數情況下這些操作不 是必需的。例如   
   Sheets(″Sheet3″).Select 
   Range(″A1″).Value = 100 
   Range(″A2″).Value = 200 
    可改爲:    With Sheets(″Sheet3″) 
    .Range(″A1″).Value = 100 
    .Range(″A2″).Value = 200 
   End With   
 

方法4:關閉屏幕更新   
如果你的 VBA程序前面三條做得比較差,則關閉屏幕更新是提高 VBA程序運行速度的最有效的方法,
縮短運行時間2/3左右。關閉屏幕更新的方法: 
  Application.ScreenUpdate = False 
請不要忘記 VBA程序運行結束時再將該值設回來: 
 Application.ScreenU pdate =Tr ue
方法5:變量類型確定,少用變體變量 
Option Explicit 語句, 在模塊級別中使用,強制顯式堀明模塊中的所有變量。 如果模塊中使用了 
Option Explicit,則必須使用  Dim、 Private、 Public、 ReDim 或 Static 語句來顯式堀明所有的變量。如果 使用了未堀明的變量名在編譯時間會出現錯誤。如果沒有使用  Option Explicit 語句,一般所有未堀明的變 量都是 Variant 類型的。 
注意 使用  Option Explicit 可以避免在鍵入已有變量時出錯,在變量的範圍不是很清楚的代碼中使用
該語句可以避免混亂 . 
方法6:關閉Excel系統提示 
'本示例關閉所有打開的工作簿。如果某個打開的工作簿有改變, Microsoft Excel 將顯示詢問是否保存
更改的對話框和相應提示。 
Workbooks.Close  實際開發程序時,需要關閉提示信息對話框,給用戶簡潔高效的體驗. 
 Application.DisplayAlerts = False   '信息警告關閉  請不要忘記 VBA程序運行結束時再將該值設回來:    Application.DisplayA lerts =Tr ue '信息警告開啓 
關閉信息警告後, 保存文檔及關閉需要先保存,在關閉   Workbooks("filename.xls").Save        '文件保存 
 Workbooks("filename.xls").Close SaveChanges:=True      '文件關閉, 不出現是否要保存的窗口,並保存所有對此工作簿的更改。       Workbooks("BOOK1.XLS").Close SaveChanges:=False         '本示例關閉  Book1.xls,並放棄所有對此工作簿的更改。       這樣可以提高程序的簡潔性,給用戶服務 .       
方法7: 提高關鍵代碼和循環代碼的效率 
不同方法執行效率的差異,但千萬不要因爲追求效率而損失了代碼的可讀性、清晰性。效率的優化必
須是針對關鍵代碼的優化,對於一些在程序執行過程中,只執行很少次數的代碼,沒有必要犧牲可讀性而 進行優化。對於代碼執行效率,千萬不要人云亦云,必要時候,自己動手測試一下,結果往往會出 乎 意料。 
代碼執行時間的測算VBA和 VB中,沒有專門的代碼執行事件測算工具和方法,筆者一般是使用 Timer
函數,其返回值是一個 Single類型的數值,代表從午夜開始到現在經過的秒數,此數值包括小數部分,但 精確程度在Windows NT,2000和 XP下大概接近 10毫秒。如果要測試一段代碼的執行速度,可以使用如 下方法: 
     Sub MeasureTime() 
      Dim Time1 As Single, Time2 As Single 
      Dim TotalTime As Single 
 

      Dim Times As Long 
      Dim i As Long 
      Times = 10000 
      Time1 = Timer 
      For i = 1 To Times Step 1 
          Mytest1 
      Next i 
      Time2 = Timer 
      TotalTime = (Time2 - Time1) * 1000 
      MsgBox "執行時間: " & TotalTime & " 毫秒(次數: " _ 
          & Times & ")" 
 End Sub
 SubMy test1()       Dim i As Long 
      Dim s As String 
      i = Rnd 
      s = Format(i, "#.00") 
 End Sub
過程 MeasureTime可以測試一個過程的執行速度,因爲一般一個過程執行會很快,所以使 用循環, 執行n次(第8行設置),在第 12行調用測試的過程,通過循環前的時間(第9行)和 循環後的時 間(第15行),計算總共執行時間(第17行)。使用這個方法,就可以做一些測試,看哪些方法執行效率 更高。另外,由於Windows的多任務特定,測試時最好關閉其他無關程序,以獲得較準確的測試結果。 
     
方法8 注意單元格寫法 
 cells(1,1) >>>>> range("a1")>>>>.[a1]   cells(1,1)符合  EXCEL 結構,最快   range("a1")有對象,稍稍慢   [A1] 寫的快,運行慢 
方法9 不要直呼其名 
a= Worksheets(1).Name >>>>> a=Worksheets("Sheet1").name 
方法10 少用 RANGE對象,可用數組取代,速度快 5-10倍, Test2就比 Test1快。 
Sub Test1()   
Dim i As Long, j As Long, buf As Long 
 For i = 1 To 10000   
 For j = 1 To 100   
 buf = Cells(i, j) 
 N ext j  
 Next  i
End Sub 
Sub Test2()   
 Dim i As Long, j As Long, buf As Long, C As Variant   
 

 C =Range("A1:CV10000" ) 
 For i = 1 To 10000   
 For j = 1 To 100   
 buf = C(i, j) 
 N ext j  
 Next  i
End Sub 
方法11 注意函數的類型 , 儘量少用 Variant變量,多用整型變量,如多用整型變量函數。 
 Chr$  ChrB$ Command$  
 CurDir$ Date$ Dir$   
 Error$ Format$ Hex$   
 Input$ InputB$ LCase$   
 LeftB$ LTrim$  
 Mid$ MidB$ Oct$   
 Right$ RightB$ RTrim$   
 Space$ Str$ String$   
 Time$ Trim$ UCase$ 
這些字符型函數 就比chr date space 等快,因爲不加後綴類型指定的函數,其返回值是 Variant類型結
果。 
第二節 結束語 
經過一禮拜的疲勞(沒功勞有苦勞,沒苦勞總有疲勞,套一句《瘋狂石頭》的電影對白) ,我總算結 束了開始的計劃,也算是有頭有尾,稍感欣慰。這期間,我要感謝各位 VBA愛好者的鼓勵和支持,你們 的堅持瀏覽讓我有信心繼續寫下去,讓我感到我寫的還有點用(不是瞎寫、亂寫的,無亂灌水之嫌疑)。 
我對程序開發,以前學過很多東西,可以說是陪着一些計算機開發語言發展走過一段時間的。記得 96

年大學時,我們學彙編語言,那時覺得像天文;覺得難,就學習 Foxbase數據庫,記得考計算機二級時, 我上機得了滿分,一下子有信心了,就轉而學習 VB5,但學來學去,就是沒法突破,後來碩士期間,我學 會了 VB6,解決了一個實際問題,這下對 VB6開發及程序開發,有了更深刻的理解;但還是覺得VB6沒 能有好的辦法解決計算機複雜的問題,比如矢量圖的繪製和保存,我就一直搞不會。後來東看西看,學了 很多計算機東西。讀博士期間,用 Excel解決數據計算和作圖,由於是要重複作類似的,所以學下了 VBA, 突然發現  Excel VBA是很適合我這種使用者—需要快速解決工作學習的實際問題, 由此我也開發了世界一 流的地化數據投圖軟件Geoplot,關於它的論文發表在 Computers & Geosciences上。在開發這個軟件期間, 學了很多東西,這些核心的東西我都在這個論壇發過貼了。所以,我隆重推薦大家學習 VBA,由於它是入 門,學習,進階都很快速,很容易上手的,是解決實際工作的最佳工具(信不信由你!)。對於其它開發語 言,我認爲目前的開發語言越來越一致了,都是以對象爲核心,比如 VB.NET,VC++.NET等,所以學會一 種 VB.NET就可以解決其它開發問題,但普通用戶來講,是不需要學會和精通那些的,只要知道有它們的 存在,且找一本書學一下,如果真的有機會,有事情需要用到那些,再學習。因爲大家都很忙,所以建議 學習 VBA這種快速解決問題的工具,看我的內容,估計一個禮拜就學會了,再看看論壇上的貼子,我想 大家一個月就能成爲 VBA中級人員。程序開發,其實還需要一定天賦的,因爲核心的算法是要靠一定智 慧的,不同的人,搞出來的,雖然都解決問題,但速度差異很大等。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/risslin/archive/2009/12/31/5111401.aspx


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章