Access的VBA缺少一个简单的Max(x,y)
函数来查找两个或更多值的数学最大值。我习惯于在其他语言(如perl/php/ruby/python等)的基本API中已经有这样的函数。
我知道可以这样做:IIf(x > y, x,y)
。还有其他可用的解决方案吗?
Access的VBA缺少一个简单的Max(x,y)
函数来查找两个或更多值的数学最大值。我习惯于在其他语言(如perl/php/ruby/python等)的基本API中已经有这样的函数。
我知道可以这样做:IIf(x > y, x,y)
。还有其他可用的解决方案吗?
我理解这个问题的意思是:
如何在Access中实现一个函数,返回一组数字的最大/最小值?以下是我使用的代码(类比于IIf,命名为“iMax”,即“立即 If” / “立即 Max”):
Public Function iMax(ParamArray p()) As Variant
' Idea from Trevor Best in Usenet MessageID rib5dv45ko62adf2v0d1cot4kiu5t8mbdp@4ax.com
Dim i As Long
Dim v As Variant
v = p(LBound(p))
For i = LBound(p) + 1 To UBound(p)
If v < p(i) Then
v = p(i)
End If
Next
iMax = v
End Function
Public Function iMin(ParamArray p()) As Variant
' Idea from Trevor Best in Usenet MessageID rib5dv45ko62adf2v0d1cot4kiu5t8mbdp@4ax.com
Dim i As Long
Dim v As Variant
v = p(LBound(p))
For i = LBound(p) + 1 To UBound(p)
If v > p(i) Then
v = p(i)
End If
Next
iMin = v
End Function
至于为什么Access不会实现它,我认为这不是一个非常普遍的需求。它也不是非常像数据库的东西。您已经拥有了在域和行集中查找最大/最小值所需的所有功能。它也不是很难实现,或者当您需要时只需编写一次比较即可。
也许以上内容可以帮助某些人。
如果您添加对Excel的引用(工具
→引用
→Microsoft Excel x.xx对象库
),则可以使用WorksheetFunction
调用大多数Excel工作表函数,包括MAX
(也可用于数组)。
示例:
MsgBox WorksheetFunction.Max(42, 1999, 888)
Dim arr(1 To 3) As Long
arr(1) = 42
arr(2) = 1999
arr(3) = 888
MsgBox WorksheetFunction.Max(arr)
第一次调用需要1秒钟才能响应(实际上对我来说是1.1秒),但随后的调用时间更加合理(对我来说每个调用<0.002秒)。
如果您在过程中使用了大量的Excel函数,您可以通过使用一个Application
对象直接引用Excel来进一步提高性能。
例如,此过程迭代一组记录,重复使用Excel的MAX
函数对字节数组进行操作,以确定每个记录的“最高”ASCII字符。
Option Compare Text
Option Explicit
'requires reference to "Microsoft Excel x.xx Object Library"
Public excel As New excel.Application
Sub demo_ListMaxChars()
'list the character with the highest ASCII code for each of the first 100 records
Dim rs As Recordset, mx
Set rs = CurrentDb.OpenRecordset("select myField from tblMyTable")
With rs
.MoveFirst
Do
mx = maxChar(!myField)
Debug.Print !myField, mx & "(" & ChrW(mx) & ")" '(Hit CTRL+G to view)
.MoveNext
Loop Until .EOF
.Close
End With
Set rs = Nothing 'always clean up your objects when finished with them!
Set excel = Nothing
End Sub
Function maxChar(st As String)
Dim b() As Byte 'declare Byte Array
ReDim b(1 To Len(st)) 'resize Byte Array
b = StrConv(st, vbFromUnicode) 'convert String to Bytes
maxChar = excel.WorksheetFunction.Max(b) 'find maximum Byte (with Excel function)
End Function
两个函数都存在空值问题,我认为这样会更好。
Public Function iMin(ParamArray p()) As Variant
Dim vVal As Variant, vMinVal As Variant
vMinVal = Null
For Each vVal In p
If Not IsNull(vVal) And (IsNull(vMinVal) Or (vVal < vMinVal)) Then _
vMinVal = vVal
Next
iMin = vMinVal
End Function
Option Compare Database
Option Base 0
Option Explicit
Function f_var_Min(ParamArray NumericItems()) As Variant
If UBound(NumericItems) = -1 Then Exit Function ' No parameters
Dim vVal As Variant, vNumeric As Variant
vVal = NumericItems(0)
For Each vNumeric In NumericItems
vVal = IIf(vNumeric < vVal, vNumeric, vVal) ' Keep smaller of 2 values
Next
f_var_Min = vVal ' Return final value
End Function
Function f_var_Max(ParamArray NumericItems()) As Variant
If UBound(NumericItems) = -1 Then Exit Function ' No parameters
Dim vVal As Variant, vNumeric As Variant
vVal = NumericItems(0)
For Each vNumeric In NumericItems
vVal = IIf(vNumeric < vVal, vVal, vNumeric) ' Keep larger of 2 values
Next
f_var_Max = vVal ' Return final value
End Function
IsNull(NumericItems)
永远不会为True
。 如果你的意图是在没有参数调用时退出该函数,请尝试检查UBound(NumericItems) = -1
。 - HansUp他们可能认为你会使用DMAX和DMIN或者SQL MAX,只能在Access数据库中工作?
我也很好奇为什么这样做...似乎在创建临时表并将表单值添加到表中,然后在表上运行DMAX或MAX查询以获取结果是一个过度的方式...
我曾经创建过一个小的projMax()函数来处理这些问题。虽然VBA可能永远不会得到增强,但以防万一他们添加了适当的Max(和Min)函数,它也不会与我的函数冲突。顺便说一句,原帖建议使用IIF...那样做是可以的,但在我的函数中,我通常会加入几个Nz()来防止null破坏函数。
你可以在Access VBA中调用Excel函数:
Global gObjExcel As Excel.Application
Public Sub initXL()
Set gObjExcel = New Excel.Application
End Sub
Public Sub killXL()
gObjExcel.Quit
Set gObjExcel = Nothing
End Sub
Public Function xlMax(a As Double, b As Double) As Double
xlCeiling = gObjExcel.Application.Max(a, b)
End Function
在Access VBA中,您可以使用Worksheetfunction.max()
或worksheetfunction.min()
。希望这能帮到您。