vba 如何检查 Access 2010 表单的实例是否仍处于打开状态?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8354927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 14:36:13  来源:igfitidea点击:

How can I check if an instance of a Access 2010 form is still open?

ms-accessvbaaccess-vbams-access-2010

提问by GazB

Preface

前言

I have a need to create multiple copies of a search form (in Access 2010) that returns a value to the calling (which is also the form that created the instance of the form).

我需要创建一个搜索表单(在Access 2010 中)的多个副本,该副本向调用返回一个值(这也是创建表单实例的表单)。

As mentioned these forms could and will have multiple copies running at the same time for example a user could want to add a company to something so they:

如前所述,这些表单可以并且将同时运行多个副本,例如,用户可能想要将公司添加到某项内容中,因此他们:

  • Click "select company" and open an instance of the company search screen
  • Then open the company editor (leaving the original company search/selection screen open) as they notice the company has a parent company that hasn't been added yet.
  • They then click the "Select Parent Company" button that opens ANOTHER instance of the search and select screen
  • They find the parent company
  • Select it which closes the second search screen and the parent company is added to the first company.
  • The user then selects the modified company using the original search screen which again closes the original search screen and returns the selected company to what ever form they originally initialised the first search...
  • 单击“选择公司”并打开公司搜索屏幕的实例
  • 然后打开公司编辑器(保持原始公司搜索/选择屏幕打开),因为他们注意到该公司有一个尚未添加的母公司。
  • 然后他们单击“选择母公司”按钮,打开另一个搜索和选择屏幕实例
  • 他们找到母公司
  • 选择它关闭第二个搜索屏幕,母公司被添加到第一个公司。
  • 用户然后使用原始搜索屏幕选择修改后的公司,这再次关闭原始搜索屏幕并将所选公司返回到他们最初初始化第一次搜索的任何形式...

This all allows the users to update and correct data as and when they find error which reduces the likelihood of them forgetting and makes it much quicker!

这一切都允许用户在发现错误时更新和更正数据,从而减少他们忘记的可能性并使其更快!

MOST of this is fine now but I have had a lot of problems with instances of a form not being able to open as a "acDialog" thus stopping the calling code running until the search was done (see this questionfor more info) and the solution I have gone with is to simulate the pausing of the calling code by using a endless loop and checking if the search screen instant is still visible. Then when the user selects something on the search screen instant it puts the value in a hidden field in the search screen and hides it's self (not closed). The calling function then sees it's hidden grabs the value from the hidden field and unloads the instant.

现在大部分都很好,但我遇到了很多问题,表单实例无法作为“acDialog”打开,因此停止调用代码运行,直到搜索完成(有关更多信息,请参阅此问题)和我采用的解决方案是通过使用无限循环并检查搜索屏幕即时是否仍然可见来模拟调用代码的暂停。然后,当用户在搜索屏幕上立即选择某些内容时,它会将值放在搜索屏幕的隐藏字段中并隐藏它自己(未关闭)。调用函数然后看到它是隐藏的,从隐藏字段中获取值并卸载瞬间。

Problem

问题

I can check if the form is hidden using FormInstant.Visable butif the user closes the form this causes an error and the code I would normally use to check if the form exists requires a form name and as it's an instant of a form all the forms have the same name! I do have a reference to the form as it is stored in a local "form" object... The code I would normally use is:

我可以使用 FormInstant.Visable 检查表单是否隐藏,但是如果用户关闭表单,这会导致错误,我通常用来检查表单是否存在的代码需要表单名称,因为它是表单所有的瞬间表格同名!我确实有对表单的引用,因为它存储在本地“表单”对象中......我通常使用的代码是:

CurrentProject.AllForms("FormName").IsLoaded

So how can I check for a instant of a form being loaded still?

那么如何检查表单是否仍然加载?

采纳答案by GazB

LOL I just realised while re-reading my msg that I can likely trap the error to work out if the form is open or not!

大声笑我刚刚在重新阅读我的消息时意识到,如果表单打开与否,我可能会发现错误!

I have quickly written this and it seems to work fine:

我很快写了这个,它似乎工作正常:

Public Function IsFormLoaded(ByRef FormToTest As Form, _
                            Optional ByRef bIsVisable As Boolean = False) As Boolean
    Dim lErrorNum As Long
    bIsVisable = False
    On Error Resume Next
        bIsVisable = NewFormClone.Visible
        lErrorNum = Err.Number
    On Error GoTo 0

    If (lErrorNum = 0) Then
        IsFormLoaded = True
    Else
        IsFormLoaded = False
    End If
End Function

Guess it doesn't really mater who answers the question as long as it is answered and the next guy/gal can use it!:)

猜猜谁回答这个问题并不重要,只要它得到回答并且下一个男人/女孩可以使用它!:)

I will leave this open for a bit and if nobody finds a better answer I will mark this as it...

我会让这个开放一段时间,如果没有人找到更好的答案,我会将其标记为...

回答by RockResolve

An old question but here's what experience taught me: If One, Two, ... instances of FormDefn opened then user closes One (Master which is the only one that can be designed), Forms(FormName) gives an error, Forms(Form) gives wrong object, but Forms(NumberIndex) does still exist with .Name = FormName!

一个老问题,但这是经验教给我的:如果打开了一个、两个、...的 FormDefn 实例,则用户关闭一个(Master 是唯一可以设计的),Forms(FormName) 给出错误,Forms(Form ) 给出了错误的对象,但 Forms(NumberIndex) 仍然存在,并且 .Name = FormName!

OpenForm creates the Forms(FormName) object. Once closed Forms(FormName) gives an error. Any "Set xForm = New Form_xxx" creates forms in the forms collection that can only be accessed by the collection number index, and cant be designed.

OpenForm 创建 Forms(FormName) 对象。一旦关闭 Forms(FormName) 就会出错。任何“Set xForm = New Form_xxx”在forms集合中创建表单,只能通过集合编号索引访问,不能设计。

So to later find a multi-instance form use something like:

所以以后找到一个多实例表单使用类似的东西:

Dim FormIdx     As Integer
Dim lForm       As Access.Form
For FormIdx = 0 To Application.Forms.Count - 1
    Set lForm = AccessFunc.Appl.Forms(FormIdx)
    If lForm.Name = pFormName Then
        IsFormOpened = True
        Set rForm = lForm
        GoTo IsFormOpened_Exit
    End If
Next

回答by user28864

Try this also

也试试这个

Function IsLoaded(strFrmName As String) As Boolean

    '  Determines if a form is loaded.

    Const conFormDesign = 0
    Dim intX As Integer

    IsLoaded = False
    For intX = 0 To Forms.Count - 1
        If Forms(intX).FormName = strFrmName Then
            If Forms(intX).CurrentView <> conFormDesign Then
                IsLoaded = True
                Exit Function  ' Quit function once form has been found.
            End If
        End If
    Next

End Function

You can call the above function it in your project like so

你可以像这样在你的项目中调用上面的函数

If Not isLoaded("MyForm") Then
 MsgBox "MyForm is Not Loaded"
End If

回答by Albert D. Kallal

I like your answer. As for the loop/wait idea? A better way is to always include a reference in each form. I useally declare form module variable called frmPrevious.

我喜欢你的回答。至于循环/等待的想法?更好的方法是始终在每个表单中包含一个引用。我通常声明名为 frmPrevious 的表单模块变量。

Create instance of form
Instance.frmPrevious = me

So now we have the form "call" some code when the form is closed in place of some "visible" + looping code setting.

所以现在我们有表单在关闭时“调用”一些代码来代替一些“可见”+循环代码设置。

So in the close code of the form we have:

所以在表单的关闭代码中,我们有:

frmPrevious.FunctionCodeToRun

The above solves a good many issues, but one is you don't need dialog (which as you note cannot use) And you also dump the need for writing "loop + wait" code from the calling code.

上面解决了很多问题,但一个是你不需要对话框(你注意到不能使用)而且你也不需要从调用代码中编写“循环+等待”代码。

This does however mean that your code continues in a new function in the calling form. I thus usually place that function right below the calling code in the calling form. I also tend to use a standard name for that function. I find this trade off worth it as opposed to loop/wait and continuing in the same code routine (I do agree this "continue" in code is often preferable, but then again having to write looping and wait code is not really that clean).

然而,这确实意味着您的代码在调用表单中的新函数中继续。因此,我通常将该函数放在调用表单中调用代码的正下方。我也倾向于为该函数使用标准名称。我发现这种权衡是值得的,而不是循环/等待并在相同的代码例程中继续(我确实同意代码中的这种“继续”通常更可取,但又不得不编写循环和等待代码并不是那么干净) .