确定函数调用是否是查询VBA中的第一个

时间:2014-05-26 00:02:39

标签: vba ms-access access-vba

有没有办法确定MS Access中的查询是否第一次调用了某个函数?我有一个查询,其中包含从VBA函数生成的字段,但需要进行一些初始化。

为了避免对查询生成的每条记录执行此操作,我想知道是否有办法确定函数调用来自查询中的第一条记录。

3 个答案:

答案 0 :(得分:2)

使用公共静态布尔变量。

Public Static isInit as Boolean

Public Function myUDF()
    If not isInit Then
        ' initializing code
        IsInit = True
    End if
    ' do stuff
End function

公共变量需要在任何选项语句之后和任何子函数之前在常规模块的顶部声明。

由于您使用此查询作为表单和报表的源,您可以重构代码,以便可以在表单/报表加载时调用函数的初始化,然后在表单/报表卸载时将isInit设置为False 。但是,在这一点上,你应该考虑一个类是否更符合你的需求,或者是否有一个纯SQL解决方案来满足你的需求。

Private Sub FormName_Load()
    Call udf_initialize
End Sub

Private Sub FormName_Unload()
    isInit = False
End Sub

答案 1 :(得分:2)

Private lastID As Integer

Function query_function(inputID As Integer) As Integer
  If (lastID <> inputID) Then
    Dim compareRST As DAO.RecordSet
    Set compareRST = CurrentDb.OpenRecordset("SELECT LAST MyTable.ID FROM MyTable;")
    lastID = compareRST!ID
    ' Do initialisation here
  End If
 ' Do other stuff here

End Function

MoveLast与LAST返回的值相同,但速度较慢。主要问题是在压缩数据库时将表重新排序为主键顺序,因此如果未按主键顺序添加记录,则压缩后MoveLast将转到其他记录。

另一个问题是,对于具有从属子查询的复杂查询,LAST子句可能应用于错误的位置。如果Id是简单递增,您可以使用MAX而不是LAST,但对于所示的简单查询并不重要。

Select queryfunction(1) as a, queryfunction(1) as b from mytable

将调用此函数4次。

每次在父查询中提到此函数时,它将被调用两次(或更多?已经有一段时间了。)

我不确定这是不是你想要做的,所以我不知道要提出什么逻辑,但因为每行调用多次,你发布的功能可能不会完全与你有关认为它确实如此。

答案 2 :(得分:0)

行。所以最后,这就是我解决它的方式。不是最好的方法。如果有人有更好的,我真的很感激。

它实际上非常hacky并且可能容易失败,它假设Query将尝试按照我们通过记录集的相同顺序查看表。这样,我们可以简单地从记录集中获取第一个值,比较它,如果它是相同的,假设我们正在查看第一个查询。它也没有那么高效,创建记录集并每次运行额外的查询。虽然至少对我而言,它的效率稍高。

Function query_function(inputID As Integer) As Integer
    Dim compareRST As DAO.RecordSet
    Set compareRST = CurrentDb.OpenRecordset("SELECT MyTable.ID FROM MyTable;")
    If compareRST![ID] = inputID Then
        ' Do initialisation here
    End If
    ' Do other stuff here
    compareRST.close
End Function

编辑 - 适用于类似主体的稍微好一点的解决方案

不是为每条记录创建新查询,而是创建查询以查找结尾,然后准备在我们到达时进行初始化。

Private lastID As Integer

Function query_function(inputID As Integer) As Integer
  If lastID = 0 Then
    Dim compareRST As DAO.RecordSet
    Set compareRST = CurrentDb.OpenRecordset("SELECT MyTable.ID FROM MyTable;")
    compareRST.MoveLast
    lastID = compareRST!ID
    ' Do initialisation here
  End If
  ' Do other stuff here

  If lastID = inputID Then
    lastID = 0
  End If
End Function