1 Excel的查找功能
VBA中應(yīng)用于Range對(duì)象的Find方法,實(shí)際上就是Excel中”Ctrl+F”出來的查找窗口。這個(gè)查找功能有一個(gè)bug(應(yīng)該是“參數(shù)After+合并單元格”的設(shè)計(jì)缺陷引發(fā)的),以在Excel中查找為例,如下圖: 故為了在VBA中對(duì)Range使用Find方法的魯棒性,自己封裝個(gè)類Find方法后開發(fā)程序會(huì)更方便,簡化定位單元格時(shí)需要書寫的代碼量。 不過,開發(fā)這一系列的函數(shù),更主要的原因是解決一些常見麻煩:單元格查找,其實(shí)大部分時(shí)候都是應(yīng)用于表頭查找,而表頭查找會(huì)有個(gè)多級(jí)表頭問題。在處理多工作表數(shù)據(jù)時(shí),還時(shí)常會(huì)遇到邏輯上是一樣的字段,但名稱有差異(如”身份證”、”身份證號(hào)碼”),給數(shù)據(jù)自動(dòng)匯總帶來不便。 對(duì)bug的修復(fù),只需加個(gè)if語句。而對(duì)于常見麻煩,我采用了一些特殊的設(shè)計(jì)理念來解決,詳見函數(shù)的使用方法。由于功能本身帶有一定模糊性,實(shí)際工作中,遇到比較復(fù)雜的表格時(shí),最好檢查下函數(shù)定位的位置是否正確(筆者也正在思考如何制作小工具進(jìn)行高效快速檢查)。
2 VBA查找功能開發(fā)
接口主要是findcel,findrow,findcol三個(gè)函數(shù),它們依次返回的是要查找的單元格本身,單元格所在行,單元格所在列。找不到時(shí)findcel返回Nothing,findrow和findcol則返回0。 輸入?yún)?shù)的規(guī)則是一樣的:第1個(gè)參數(shù)st是要查找的工作表,第2個(gè)參數(shù)name是要查找的值,函數(shù)會(huì)優(yōu)先按照“單元格匹配”的規(guī)則進(jìn)行查找,找不到的情況下,會(huì)去掉“單元格匹配”再進(jìn)行查找。
'代碼更新于2015年07月30日
Function findcol(ByVal st As Worksheet, ByVal name As String, Optional ByVal partName As String) As Long
Dim t As Range
Set t = findcel(st, name, partName)
If t Is Nothing Then
findcol = 0
Else
findcol = t.Column
End If
End Function
Function findrow(ByVal st As Worksheet, ByVal name As String, Optional ByVal partName As String) As Long
Dim t As Range
Set t = findcel(st, name, partName)
If t Is Nothing Then
findrow = 0
Else
findrow = t.Row
End If
End Function
'該函數(shù)支持name、partName用分號(hào)隔開,允許按優(yōu)先級(jí)進(jìn)行字段名搜索的多字段查詢
Function findcel(ByVal st As Worksheet, ByVal name As String, Optional ByVal partName As String) As Range
'(1)首先name絕對(duì)不能為空
If name = '' Then Exit Function
Dim arr1, arr2
'(2)partName可以為空,但為了后續(xù)遍歷統(tǒng)一處理,需要先預(yù)分析下
arr1 = Split(partName, ';')
If isEmptyArr(arr1) Then
ReDim arr1(1 To 1)
arr1(1) = ''
End If
'(3)開始循環(huán)遍歷,只要找到第一組滿足解即可
arr2 = Split(name, ';')
For Each a1 In arr1
For Each A2 In arr2
Set findcel = findcel_base(st, A2, a1)
If Not (findcel Is Nothing) Then Exit Function
Next A2
Next a1
End Function
Function findcel_base(ByVal st As Worksheet, ByVal name As String, Optional ByVal partName As String) As Range
Dim rng As Range '查找的范圍
Set rng = st.UsedRange
'Debug.Print 'findcel_base查找內(nèi)容所在工作薄', st.Parent.name
Dim rng2 As Range, t As Range
'(1)先定位高級(jí)表頭的列范圍
If partName <> '' Then
Set t = rng.Find(partName, LookAt:=xlPart)
'如果第一個(gè)是合并單元格,有時(shí)候會(huì)有找不到的bug
If rng.Cells(1, 1) = partName Then Set t = rng.Cells(1, 1)
'如果確實(shí)找不到,退出函數(shù)
If t Is Nothing Then Exit Function
'否則就是找到了,計(jì)算出找到的(合并)單元格所在列
Set rng2 = st.Range(rng.Cells(1, t.Column), rng.Cells(st.Rows.Count, t.Offset(0, 1).Column - 1))
Set rng = Intersect(rng, rng2) 'Range的交
End If
'(2)然后就可以直接在rng搜索表頭名了
Set t = rng.Find(name, LookAt:=xlWhole) '能單元格匹配找到,則按照單元格結(jié)果
If t Is Nothing Then Set t = rng.Find(name, LookAt:=xlPart) '否則進(jìn)行部分查找
If name = rng.Cells(1, 1) Then Set t = rng.Cells(1, 1)
'If Not (t Is Nothing) Then Debug.Print name & '在' & t.Address
Set findcel_base = t
End Function
Private Function isEmptyArr(arr) As Boolean '
isEmptyArr = True
For Each a In arr
isEmptyArr = False
Exit For
Next a
End Function
3 使用舉例
測(cè)試代碼:
Sub 表頭查找與定位()
Dim st As Worksheet
Set st = ActiveSheet
'(1)可以用'格式比較穩(wěn)定'的字段來定位表頭所在行
Dim p As Range
Set p = findcel(st, '物理站址編號(hào)')
Debug.Print '表頭行范圍:', p.Row & '~' & (p.Offset(1, 0).Row - 1)
'(2)定位幾個(gè)字段的位置
Debug.Print '基本定位功能:'
Debug.Print findcol(st, '序號(hào)'), '序號(hào)'
Debug.Print findcol(st, '面積'), '機(jī)房面積(平方米)' '模糊匹配
Debug.Print findcol(st, '資產(chǎn)名稱'), '有多個(gè)滿足時(shí),返回第1個(gè)匹配結(jié)果'
Debug.Print findcol(st, '賬面凈額'), '賬面凈額R-S-T'
Debug.Print findcol(st, '設(shè)備類型'), '找不到時(shí)返回0值'
Debug.Print '高級(jí)定位功能:'
Debug.Print findcol(st, '設(shè)備名稱;資產(chǎn)名稱'), '找不到設(shè)備名稱后,繼續(xù)找資產(chǎn)名稱'
Debug.Print findcol(st, '原值', '評(píng)估價(jià)值2'), '多級(jí)表頭查找與定位'
Debug.Print findcol(st, '總值;價(jià)值;原值;凈值', '評(píng)估值;評(píng)估價(jià)值'), '多功能混用'
End Sub
處理對(duì)象:
立即窗口輸出的結(jié)果:
表頭行范圍: 1~2
基本定位功能:
1 序號(hào)
5 機(jī)房面積(平方米)
4 有多個(gè)滿足時(shí),返回第1個(gè)匹配結(jié)果
6 賬面凈額R-S-T
0 找不到時(shí)返回0值
高級(jí)定位功能:
4 找不到設(shè)備名稱后,繼續(xù)找資產(chǎn)名稱
12 多級(jí)表頭查找與定位
9 多功能混用
|