VBA,使用find() 和 match() 進行查找時,可能出現的各種錯誤(我犯的各種錯誤總結)

最近因爲在窗體裏要做對工作表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有很多出錯數字

 

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