自用Excel VBA函数整理 part1
用于二维的Dictionary:
CreateOrSet2
HasValue2
数字-字母格式的列号互转:
ColNumToStr
ColStrToNum
字符串连接(类似String.Format()用{0}{1}等做占位符,实现得很土):
StrFormat
StrCat
在Workbook中保存基本类型值:
SetName, GetName
函数指针(用VB->Win API->VB的模拟,参考[1][2]):
另外Application.Run、CallByName、Eval和Evaluate可能更实用,VB6/VBA杂就没一个像js或py那样的全能eval()函数呢。。。
Fn4及例子
初级版ArrayList(类模块):
Class ArrayList
Private arr() As Variant
Private size, capacity As Integer
Private Sub Class_Initialize()
size = 0
capacity = 10
ReDim arr(1 To capacity)
End Sub
Public Property Get Count() As Integer
Count = size
End Property
Public Property Get Item(idx)
Item = arr(idx)
End Property
Public Property Let Item(idx, vlu)
arr(idx) = vlu
End Property
Public Property Set Item(idx, obj)
Set arr(idx) = obj
End Property
Public Sub Add(elem)
EnsureCapacity
size = size + 1
If IsObject(elem) Then
Set arr(size) = elem
Else
arr(size) = elem
End If
End Sub
Private Sub EnsureCapacity()
If (size + 1) > capacity Then
ReDim Preserve arr(1 To capacity * 2) 'Preserve!
capacity = capacity * 2
End If
End Sub
Public Sub Clear()
size = 0
End Sub
Public Function IndexOf(elem) As Long
idx& = -1
elemObj = IsObject(elem)
For i = 1 To size
If elemObj Then
If IsObject(arr(i)) Then
If ObjPtr(arr(i)) = ObjPtr(elem) Then
idx = i
Exit For
End If
End If
Else
If Not IsObject(arr(i)) Then
If arr(i) = elem Then
idx = i
Exit For
End If
End If
End If
Next i
IndexOf = idx
End Function
Public Sub Delete(elem)
idx = IndexOf(elem)
If idx <> -1 Then
DeleteAt idx
End If
End Sub
Public Sub DeleteAt(idx)
For i = idx To (size - 1)
If IsObject(arr(i + 1)) Then
Set arr(i) = arr(i + 1)
Else
arr(i) = arr(i + 1)
End If
Next i
size = size - 1
End Sub
Public Function GetArray()
Dim ret() As Variant
ReDim ret(1 To size)
For i = 1 To size
ret(i) = arr(i)
Next i
GetArray = ret
End Function
Private size, capacity As Integer
Private Sub Class_Initialize()
size = 0
capacity = 10
ReDim arr(1 To capacity)
End Sub
Public Property Get Count() As Integer
Count = size
End Property
Public Property Get Item(idx)
Item = arr(idx)
End Property
Public Property Let Item(idx, vlu)
arr(idx) = vlu
End Property
Public Property Set Item(idx, obj)
Set arr(idx) = obj
End Property
Public Sub Add(elem)
EnsureCapacity
size = size + 1
If IsObject(elem) Then
Set arr(size) = elem
Else
arr(size) = elem
End If
End Sub
Private Sub EnsureCapacity()
If (size + 1) > capacity Then
ReDim Preserve arr(1 To capacity * 2) 'Preserve!
capacity = capacity * 2
End If
End Sub
Public Sub Clear()
size = 0
End Sub
Public Function IndexOf(elem) As Long
idx& = -1
elemObj = IsObject(elem)
For i = 1 To size
If elemObj Then
If IsObject(arr(i)) Then
If ObjPtr(arr(i)) = ObjPtr(elem) Then
idx = i
Exit For
End If
End If
Else
If Not IsObject(arr(i)) Then
If arr(i) = elem Then
idx = i
Exit For
End If
End If
End If
Next i
IndexOf = idx
End Function
Public Sub Delete(elem)
idx = IndexOf(elem)
If idx <> -1 Then
DeleteAt idx
End If
End Sub
Public Sub DeleteAt(idx)
For i = idx To (size - 1)
If IsObject(arr(i + 1)) Then
Set arr(i) = arr(i + 1)
Else
arr(i) = arr(i + 1)
End If
Next i
size = size - 1
End Sub
Public Function GetArray()
Dim ret() As Variant
ReDim ret(1 To size)
For i = 1 To size
ret(i) = arr(i)
Next i
GetArray = ret
End Function
运行一个SQL查询并填充到工作表上:
ExecuteSelect
Public Sub ExecuteSelect(connStr, selectTxt, destTopLeft As Range)
On Error GoTo ExecuteSelect_Err
Set ws = destTopLeft.Worksheet
Set conn = CreateObject("ADODB.Connection")
conn.Open connStr
Set rs = conn.Execute(selectTxt)
For i = 0 To rs.Fields.Count - 1
destTopLeft.Offset(0, i) = rs.Fields(i).Name
Next i
destTopLeft.Offset(1, 0).CopyFromRecordset rs
ExecuteSelect_Clean:
If Not IsEmpty(rs) Then
rs.Close
End If
If Not IsEmpty(rs) Then
conn.Close
End If
Set rs = Nothing
Set conn = Nothing
Exit Sub
ExecuteSelect_Err:
MsgBox "Error " & Err.Number & " (" & Err.Description & ")"
GoTo ExecuteSelect_Clean
End Sub
On Error GoTo ExecuteSelect_Err
Set ws = destTopLeft.Worksheet
Set conn = CreateObject("ADODB.Connection")
conn.Open connStr
Set rs = conn.Execute(selectTxt)
For i = 0 To rs.Fields.Count - 1
destTopLeft.Offset(0, i) = rs.Fields(i).Name
Next i
destTopLeft.Offset(1, 0).CopyFromRecordset rs
ExecuteSelect_Clean:
If Not IsEmpty(rs) Then
rs.Close
End If
If Not IsEmpty(rs) Then
conn.Close
End If
Set rs = Nothing
Set conn = Nothing
Exit Sub
ExecuteSelect_Err:
MsgBox "Error " & Err.Number & " (" & Err.Description & ")"
GoTo ExecuteSelect_Clean
End Sub