最近因爲在窗體裏要做對工作表sheet的操作,出現了各種低級錯誤
我逐一在這總結下,希望自己反思,並以後引以爲戒
數據源
1 正確的代碼
應該也有多種寫法
Sub test5032()
Dim a As Range
in1 = InputBox("請輸入一個電影名")
Set a = Range("a1:a15").Find(in1)
If a Is Nothing Then
Range("A" & 1 + Range("a65536").End(xlUp).Row).Value = in1
Else
MsgBox "內容重複了"
End If
End Sub
2 典型錯誤1:判斷 range().find() 返回值亂用null,err這些
2.1 使用 range().if() 查找時,對其返回值不合適的 判斷函數
2.1.1 這3種用法的結果不同
- range().find()
- 如果查得到,返回的是rang()
- 如果查不到,返回的是nothing()
- 判斷條件只能是 :
- dim a as range
- set a =range().find()
- if a is nothing
- 語法不能寫成 if a =nothing
- a.value is nothing 也報對象變量錯誤,因爲nothing 是專門給對象變量用的
- 錯誤的判斷條件, 查不到返回 nothing 而不是 err ,用 a=err等判斷,始終都會爲否
- if a=err then
- if iserror(a) then
- 錯誤的判斷條件, 不明白爲啥 nothing 不是 null 或 empty ? 用isnull() ispempty() 判斷始終都爲否
- 都是判斷變量的值的函數
- if isnull() then
- if isempty() then
2.1.2 錯誤代碼舉例:如果用 isnull() 和 isempty(),下面的if 始終只會判斷爲否
錯誤原因
- empty 有效的空值,如0 ""
- null 無效的控制,比如二選一之外的空
- nothing 對象變量的空值
Sub test50411()
Dim a As Range
in1 = InputBox("請您輸入1個電影名")
Set a = Range("a1:a15").Find(in1)
If IsNull(a) Then
Range("A" & 1 + Range("a65536").End(xlUp).Row) = in1
Else
MsgBox "內容重複了"
End If
End Sub
2.1.3 empty null nothing 三者的區別
- 參考文章:https://www.cnblogs.com/lys_013/archive/2013/04/16/3024229.html
- Empty、Null和Nothing都可爲Variant變量賦值
- 聲明時系統會設Variant變量爲Empty
- 如果要將Variant變量設爲無效數據可用Null
- 如果不再使用對象變量就應儘快將之設成Nothing以利系統釋放資源。
3 典型錯誤:使用range().find() 必須先做錯誤處理,再處理正常流程
3.1 range().find()如果查不到,或者查找的類型不匹配會報錯
- 因爲 range().find() 不事先處理報錯導致的報錯
- 典型錯誤,沒有先做異常處理會導致報錯,想到find()函數的應該先進行出錯處理,再處理正常流程
3.1.1 思路的學習,以後用 find() 和if 要考慮全面點,先考慮出錯可能和如何處理出錯
新思路:應該先考慮異常邏輯和進行異常處理,然後再處理正常邏輯。
- 分析出錯的原因:
- 我的老思路:用 find() 來查找,先判斷是否重複,如果重複就報錯,如果不重複就新增1條記錄
- 問題是
- range().find() 如果查找不到會報錯。
- 所以應該先判斷,是否會出錯,然後馬上解決出錯後如何處理。然後再去處理正常邏輯。
- 以後使用range().find() 必須先做錯誤處理,否則可能會先跳出報錯而中斷
- 先要考慮出錯的可能
- 還要想到如何處理出錯的手段
- 而不是上來開始正常的邏輯過程
3.1.2 中間變量挺重要
- 中間變量很重要
- 不光是把一些數據存起來
- 而且防止了傳送過程中數據發生變化
3.2.1 錯誤代碼
Sub test50323() '這是一個錯誤代碼,舉例
Dim a As Range
in1 = InputBox("請輸入一個電影名")
Set a = Range("a1:a15").Find(in1)
If Range("a1:a15").Find(in1) = in1 Then '一旦這個找不到就會報錯
MsgBox "內容重複了"
Else
Range("A" & 1 + Range("a65536").End(xlUp).Row).Value = in1
End If
End Sub
3.2.2 修正代碼---還是錯的---不知道爲什麼還是隻走一個分支
- 加了 on error resume next
- if 先判斷了find()到
- 結果還是隻走上面的分支?
Sub test50323()
Dim a As Range
in1 = InputBox("請輸入一個電影名")
Set a = Range("a1:a15").Find(in1)
On Error Resume Next
Debug.Print "Range("" a1: a15 "").Find(in1)="
Debug.Print "Range("" a1: a15 "").Find(in1)=" & Range("a1:a15").Find(in1).Address '因爲出錯,整句都不會打印?
If Range("a1:a15").Find(in1) = in1 Then '不知道爲什麼這麼改了,爲什麼還只有一個分支?
MsgBox "內容重複了"
Else
Range("A" & 1 + Range("a65536").End(xlUp).Row).Value = in1
End If
End Sub
4 典型低級錯誤
4.1 使用語法錯誤:設置變量對象時,賦值語法不對,沒有用set
- 對象變量沒設置好也會報錯,也是報錯,對象變量或with變量未設置
- 雖然報錯一樣,但是和 range().find() 方法查不到而報錯,本質不一樣
Sub test50311()
' 典型錯誤,沒有保存變量的
Dim a As Range
Set a = Range("a1:a15").Find(InputBox("請輸入一個電影名"))
If a Is Nothing Then
Range("A" & 1 + Range("a65536").End(xlUp).Row).Value = InputBox("請輸入一個電影名") 'TextBox1 不在窗體裏報錯,不應該在initial做歌詞初始化
Else
MsgBox "內容重複了"
End If
End Sub
4.2 典型錯誤:多用中間變量保存數據,然後再傳遞和使用,而不是每次臨時處理。
- 我這又犯了新手常犯的錯誤
- 輸入的數據應該用變量保存下來,裝到變量盒子裏
- 典型錯誤,沒有保存變量值,多次使用inputbox,這樣是不對的
Sub test50311()
' 典型錯誤,沒有使用中間變量保存和傳遞數據
' 錯誤的使用2次inputbox() ,第2個input和第一次木關係了
' 典型新手會犯的錯誤
Dim a As Range
Set a = Range("a1:a15").Find(InputBox("請輸入一個電影名"))
If a Is Nothing Then
Range("A" & 1 + Range("a65536").End(xlUp).Row).Value = InputBox("請輸入一個電影名") 'TextBox1 不在窗體裏報錯,不應該在initial做歌詞初始化
Else
MsgBox "內容重複了"
End If
End Sub
4.3 典型錯誤:用 分支判斷時,誰的值?
- If Err Then ’典型錯誤,這種純粹SX的錯誤 if 誰?=err? then
- If a = Err Then '記得應該是判斷某個變量,或者 表達式的值 爲err
- 另外 false <> err
- if true then '這是故意的寫法,就是故意只執行false的分支!
- 不要隨便混用
- true false '這個是bool值
- error '錯誤值
5 不合適的功能函數,使用application.find() 導致的錯誤
5.1 application.find() 和worksheetfunction.find() 本質是工作表函數 ---查找的範圍主要還是 字符串內string
- 如果使用的功能函數,是工作表函數,會出問題
- 工作表函數, application.find() 返回的是 查找內容在 字符串 string 內的 第幾個位置。
- application.find() 返回值,用 isempty() iserror() =null =err 判斷了都不行,不知道怎麼搞
Sub test504() ---錯誤代碼,舉例
On Error Resume Next
in1 = InputBox("請您輸入1個電影名")
a = Application.Find(in1, Range("a1:a15"))
If IsError(a) Then '嘗試過 isempty() =err =null 等都不行
Debug.Print "沒找到"
Range("A" & 1 + Range("a65536").End(xlUp).Row) = in1
Else
Debug.Print "找到了"
MsgBox "內容重複了"
End If
End Sub
6 使用match() 函數也會遇到類似的問題
- application.match() 本質也是工作表函數
- 和 range().find() 不一樣,rang().find()返回的是 range() 對象,find不到位空對象變量是 is nothing
- 而application.match() 查到的是一個index 對應的數。如果查不到會報錯,而報錯是err=0
6.1 錯誤的寫法
- 錯誤的思路:沒有先考慮出錯處理
- application.match() 查不到會報錯,無法取得 match 屬性
正確代碼
- 使用查找,匹配函數時,要先進行錯誤處理
- 但同時要對錯誤值和空值有區分,
- 如果需要處理錯誤值,則要可能要先加一個語句 on error resume next
- 如果要處理空值,得注意是對象變量是 is nothing ,其他變量 則可能是 empty 或者 null 等
Sub aa31()
On Error Resume Next
in1 = Int(InputBox("請輸入1個要查的數字"))
a = WorksheetFunction.Match(in1, Array(1, 2, 3, 4, 5), 0)
If Err = 0 Then
Debug.Print a
Else
Debug.Print "沒找到!"
End If
End Sub
err的具體值
- 最初猜想:err是布爾值?err=0 表示沒錯誤, err=1 表示是出錯了
- 測試代碼,換ERR=1,且調換IF判斷次序,結果找不到就不反饋,有問題
Sub aa32() ---測試代碼,換ERR=1,且調換IF判斷次序,結果找不到就不反饋,有問題
On Error Resume Next
in1 = Int(InputBox("請輸入1個要查的數字"))
a = WorksheetFunction.Match(in1, Array(1, 2, 3, 4, 5), 0)
If Err = 1 Then
Debug.Print "沒找到!"
Else
Debug.Print a
End If
End Sub
err 其實是 err.number
- err=0 表示 err.number=0 沒出出錯
- err.number有很多出錯數字