VBE有豐富的調試工具, 比如立即窗口, 本地窗口, 監視窗口, 斷點調試...
第一個博文中已經講過調試的基本操作: 設置斷點, F5運行, F8逐條運行
斷點就是程序中暫停停止運行的位置, 設置斷點之后, 當運行到斷點行所在的語句程序就進入中斷模式,
此時在本地窗口和立即窗口中 可以查看變量以及對象的屬性值.
1. debug 介紹: 調試工具的基石
debug.print x 在不中斷程序的情況下輸出x 的值
debug.assert 與if 類似, 用與判斷一個條件是否成立, 但是if 語句不會暫定程序的執行, 如果assert方法的參數不成立,
程序會暫停進入中斷模式.
Function assert_test(x As Integer, y As Integer) As Double Debug.Assert y <> 0 ' y=0則進入中斷模式 If y <> 0 Then assert_test = x / y End If End Function Sub test() MsgBox assert_test(10, 2) ' 正常運行 MsgBox assert_test(10, 0) ' 在Debug.Assert y <> 0 程序會中斷 End Sub
立即窗口的使用 : 立即窗口的輸出如果超過200行, 就只顯示最后200行的內容
打印的關鍵字是 print 或者?
print assert_test(10,3) 3.33333333333333 ?sqr(2) ' 按下Enter 1.4142135623731
其他
for each sh in sheets: debug.Print sh.name: next ' Enter Sheet8 Sheet9 Sheet10
其他
for i =1 to 4 : debug.Print i*i: next i 1 4 9 16
本地窗口的使用: 單步調試下, 本地窗口可以查看當前過程的所有變量和對象的狀態(視圖-->本地窗口), 很簡單不敘述了...
監視窗口比本地窗口靈活, 可以自己選擇想要查看的變量, 這個在Excel入門系列第一篇博文中已經講過...
2. 錯誤處理
一般錯誤分為三種:
(1) 編輯錯誤: 不正確的代碼導致的, 沒有end if 等
(2) 運行時錯誤: 試圖執行一個不可能完成的任務: 重命名已經打開的文件, 被除數是0....
(3) 邏輯錯誤: 語法正確, 操作正當情況下還是沒有出想要的結果
on error 語句捕捉錯誤並進行處理, 告訴程序發生錯誤時需要轉到哪個地方進行處理
on error goto line | resume next | goto 0
on error goto line 啟動錯誤處理程序, line 參數表示行標簽或者行號, 必須和 on error 在同一個過程中.
Sub errtest() On Error GoTo errhandle 'errhandle為標簽 ChDrive "A" Exit Sub errhandle: MsgBox "程序出錯, 請聯系技術人員" & vbCrLf & "錯誤編號:" & _ Err.Number & "," & Err.Description, vbInformation, "錯誤提示" Err.Clear End Sub
vbcrlf 表示換行
chDrive "A" 表示磁盤驅動器A沒有插入軟盤時將彈出 設備不可用的 提示
得到結果:

或者用行號表示, 隨便一個數字就行! 不是真的行號
Sub errtest() On Error GoTo 11 'errhandle為標簽 ChDrive "A" Exit Sub 11 MsgBox "程序出錯, 請聯系技術人員" & vbCrLf & "錯誤編號:" & _ Err.Number & "," & Err.Description, vbInformation, "錯誤提示" Err.Clear End Sub
如果發生錯誤不影響后面的程序, 那么直接就寫 on error resume next
3. 代碼優化
實例1: 一般工作表函數比普通VBA代碼更有效率
Sub test() Dim num As Long, i As Integer, tm As Date Dim Cell tm = Timer For i = 1 To 1000 ' 只是為了增加循環次數 For Each Cell In Range("A1:A80") num = num + Cell.Value Next Next i Debug.Print "普通運行時間1:" & Format((Timer - tm), "0.0000") & "秒" tm = Timer For i = 1 To 1000 num = WorksheetFunction.Sum(Range("A1:A80")) Next i Debug.Print "用sum函數的運行時間2:" & Format((Timer - tm), "0.0000") & "秒" End Sub
普通運行時間1:0.3359秒
用sum函數的運行時間2:0.0078秒.
實例2: 減少對象的激活或者選擇
初學者很喜歡用錄制宏, 但是錄制宏得到代碼很冗余, 有很多的select , activate 語句, 實際上很多對象的操作是不需要激活該對象的.
例如當前工作表是sheet1, 現在要給sheet2 的區域A1 賦值
' 錄制宏得到的 Sheet2.Select Range("A1").Select ActiveCell.Value = "Hello" ' 實際很簡單 Sheet2.Range("A1").Value = "Hello"
實例3: 少用variant 類型的變量
variant 比較省事, 但是variant 需要占用很多的內存,(integer 占用2個字節, long數據占用4個字節, 全數字的variant 數據占用16個字節)
你可以設置不同的變量進行運算10000次比較運行時間.
實例4: 減少用. 點的數量
對於對象屬性的調用, 一般采用 object.method. 點的數量越少速度越快.
對同一對象的重復引用, 可以設置一個變量
ThisWorkbook.Sheets("try").Cells(1, 1) = 1 ThisWorkbook.Sheets("try").Cells(1, 2) = 3 ThisWorkbook.Sheets("try").Cells(1, 3) = 4 ' set Set w = ThisWorkbook.Sheets("try")
也可以用with 語句
With ThisWorkbook.Sheets("try") .Cells(1, 1) = 100 .Cells(1, 2) = 200 End With
實例4: 用數組代替range
如果只對range對象中的單元格的值進行處理, 而不用到單元格的屬性和方法, 可以使用數組處理range對象.
數組的處理速度遠遠快於range對象的運算速度
Dim arr() arr = Range("A1:E400") ' 生成一個400行6列的二維數組
數組arr必須定義為variant 類型, 數組的下表下界是1, 並且不受option base 的影響.
注意, 即使引用的范圍只有一行或者一列, 賦值的數組仍然是二維數組
arr(range("A1:A4"))
賦值之后, arr即為一個arr(1 to 44, 1 to 1)的二維variant 數組, 元素的下標為arr(1,1), arr(2,1), arr(3,1), arr(4,1).
經過數據處理之后, 把數組變量寫入工作表區域中: range("A1:E400")=arr
實例5: 讓代碼"專注"運行--> 關閉屏幕刷新
在過程的一開始寫: Application.ScreenUpdating = False
在結果的時候Application.ScreenUpdating = True 還原設置
實例6: 單元格/區域的表示方法
cells(1,1), range("A1"), [A1] 三種方法中cells(1,1)是最快的, [A1]最慢
但是三種方法各有各的優點, cells(1,1)可以精確的獲得單元格的行列, range("A1") 可以獲得屬性與方法
對於工作表, sheets(1) 比sheets("sheet1") 速度快, 其實VBA看到名稱時, 先把名稱解析為索引.
