Access中没有max(x,y)函数

时间:2009-08-31 02:12:30

标签: vba ms-access access-vba max worksheet-function

VBA for Access缺少一个简单的Max(x,y)函数来查找两个或更多值的数学最大值。我习惯于在基础API中已经有来自其他语言的这样的函数,例如perl / php / ruby​​ / python等。

我知道可以做到:IIf(x > y, x,y)。还有其他解决方案吗?

8 个答案:

答案 0 :(得分:7)

我会将这个问题解释为:

如何在Access中实现一个返回数字数组的最大值/最小值的函数?这是我使用的代码(通过与IIf类比命名为“iMax”,即“Immediate If”/“Immediate 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不会实现它,在我看来,这不是一件非常普遍的事情。它也不是非常“数据集”。您已经拥有了跨域和行集查找Max / Min所需的所有功能。它也不是很难实现,或者只是在需要时进行一次性比较。

上述情况可能对某人有所帮助。

答案 1 :(得分:2)

从MS Access VBA调用Excel VBA函数

如果您向Excel 添加引用ToolsReferencesMicrosoft Excel x.xx Object Library),则可以使用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秒),但是随后的电话则更为合理(对我来说每个<0.002秒)。


将Excel视为对象

如果您在过程中使用许多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

答案 2 :(得分:1)

因为他们可能认为您将使用DMAX和DMIN或sql MAX并且仅在访问中使用数据库?

我也很好奇为什么..它似乎有点过分需要创建一个临时表并向表中添加表单值然后在表上运行DMAX或MAX查询以获得结果... < / p>

答案 3 :(得分:1)

我已经知道创建一个小的projMax()函数来处理这些问题。并不是说VBA可能会被增强,但是为了防止它们添加适当的Max(和Min)函数,它不会与我的函数冲突。 BTW,最初的海报建议做IIF ...这有效,但在我的功能中,我通常会抛出几个Nz()以防止null破坏功能。

答案 4 :(得分:1)

我喜欢DGM使用IIF语句和David使用For / Next循环,因此我将它们组合在一起。

由于访问中的VBA没有严格的类型检查,我将使用varients来保留所有数字,整数和小数,并重新输入返回值。

感谢HansUP接受我的参数验证:)
添加了评论以使代码更友好。

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

两个函数之间的唯一区别是IIF语句中vVal和vNumeric的顺序。
for each子句使用内部VBA逻辑来处理循环和数组边界检查,而“Base 0”启动数组索引为0。

答案 5 :(得分:1)

两个函数都有Null的问题。我认为这会更好。

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

答案 6 :(得分:0)

您可以在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

答案 7 :(得分:-1)

您可以在Access VBA中执行Worksheetfunction.max()worksheetfunction.min()。希望这可以帮助。