在Access中从Excel运行宏,但在运行

时间:2016-11-09 20:10:32

标签: excel vba excel-vba ms-access access-vba

我从Excel VBA打开Microsoft Access并运行宏,然后在Excel中运行更多代码。几天前一切都很好,但现在我有两个问题。运行宏后,First Access不会关闭,因此Excel会超时(它会弹出一个消息框,说明Microsoft Excel正在等待另一个应用程序完成OLE操作)。这实际上是另一个问题,因为当它超时我必须再次与Excel交互以使Excel中的宏继续运行。在我第一次在Excel中启动宏之前,我尝试不必触摸任何内容,直到完成为止。而且我认为它也可能超时,因为我在Access中向我的宏添加了更多步骤,因此需要更长的时间......

首先,这是调用Access的Excel代码:

Sub Opendatabase()

Dim accessApp
Set accessApp = CreateObject("Access.Application")
accessApp.Visible = True
accessApp.OpenCurrentDataBase ("I:\MyPath\MyFile.accdb")
accessApp.Run "ImportDataRunQueriesExportData"


'Run the next part of Excel macro
Application.Run "PullinTheExportedAccessData"

End Sub

然后在Access中,它会这样做(抱歉,它太长了)。它的目的是提取数据,运行查询(我打开和关闭它们,我不确定是否有更快的方法),然后导出数据。我希望它也在最后结束,而且现在这部分不起作用。

Sub ImportDataRunQueriesExportData()

DoCmd.RunSavedImportExport "Import-ERT Aggregate Macro"

'Open master book January to refresh

 DoCmd.SetWarnings False
 DoCmd.OpenQuery ("Remove HP not Area8")
 DoCmd.OpenQuery ("Remove Non Area 8 HP")
 DoCmd.SetWarnings True
DoCmd.OpenTable ("Remove HPnonArea8")
DoCmd.Close acTable, "Remove HPnonArea8"
DoCmd.OpenQuery ("Summary For January")

'Open Duplicate search queries across all c
DoCmd.OpenQuery ("S+D")
DoCmd.OpenQuery ("S+D+L")
DoCmd.OpenQuery ("S+D+L+F")
DoCmd.OpenQuery ("S+D+L+F+M")
'Open Duplicate search queries within c
DoCmd.OpenQuery ("C+S+D")
DoCmd.OpenQuery ("C+S+D+L")
DoCmd.OpenQuery ("C+S+D+L+F")
DoCmd.OpenQuery ("C+S+D+L+F+M")


'Save and close queries, made with create Macro function
    DoCmd.Close acQuery, "Summary For January"
    DoCmd.Close acQuery, "S+D"
    DoCmd.Close acQuery, "S+D+L"
    DoCmd.Close acQuery, "S+D+L+F"
    DoCmd.Close acQuery, "S+D+L+F+M"
    DoCmd.Close acQuery, "C+S+D"
    DoCmd.Close acQuery, "C+S+D+L"
    DoCmd.Close acQuery, "C+S+D+L+F"
    DoCmd.Close acQuery, "C+S+D+L+F+M"

'Open Summary Queries
DoCmd.OpenQuery ("New January")
DoCmd.OpenQuery ("Renew January")
DoCmd.OpenQuery ("Count October")
DoCmd.OpenQuery ("Count November")
DoCmd.OpenQuery ("Count December")
DoCmd.OpenQuery ("5B")
DoCmd.OpenQuery ("5CW")
DoCmd.OpenQuery ("5ML")
DoCmd.OpenQuery ("5M")
DoCmd.OpenQuery ("5S")
DoCmd.OpenQuery ("RA")

'Save and close queries and table
    DoCmd.Close acQuery, "New January"
    DoCmd.Close acQuery, "Renew January"
    DoCmd.Close acQuery, "Count October"
    DoCmd.Close acQuery, "Count November"
    DoCmd.Close acQuery, "Count December"
    DoCmd.Close acQuery, "5B"
    DoCmd.Close acQuery, "5CW"
    DoCmd.Close acQuery, "5ML"
    DoCmd.Close acQuery, "5M"
    DoCmd.Close acQuery, "5S"
    DoCmd.Close acQuery, "RA"

'Make Table, delete w/in c dups, Open Data Table S D Between C, close table
  DoCmd.SetWarnings False

  DoCmd.OpenQuery ("Table S+D")
  DoCmd.OpenQuery ("Delete C+S+D")

  DoCmd.SetWarnings True

DoCmd.OpenTable ("S D Between C")
DoCmd.Close acTable, "S D B C"

'Run saved exports of the queries to folder
DoCmd.RunSavedImportExport "Export-S+D"
DoCmd.RunSavedImportExport "Export-S+D+L"
DoCmd.RunSavedImportExport "Export-S+D+L+F"
DoCmd.RunSavedImportExport "Export-S+D+L+F+M"
DoCmd.RunSavedImportExport "Export-C+S+D"
DoCmd.RunSavedImportExport "Export-C+S+D+L"
DoCmd.RunSavedImportExport "Export-C+S+D+L+F"
DoCmd.RunSavedImportExport "Export-C+S+D+L+F+M"
DoCmd.RunSavedImportExport "Export-New January"
DoCmd.RunSavedImportExport "Export-Renew January"
DoCmd.RunSavedImportExport "Export-Count October"
DoCmd.RunSavedImportExport "Export-Count November"
DoCmd.RunSavedImportExport "Export-Count December"
DoCmd.RunSavedImportExport "Export-5B"
DoCmd.RunSavedImportExport "Export-5CW"
DoCmd.RunSavedImportExport "Export-5ML"
DoCmd.RunSavedImportExport "Export-5M"
DoCmd.RunSavedImportExport "Export-5S"
DoCmd.RunSavedImportExport "Export-S D Between C"
DoCmd.RunSavedImportExport "Export-RA"

    Dim n As Integer
    Dim db As DAO.Database

    Set db = CurrentDb
    For n = db.TableDefs.Count - 1 To 0 Step -1
    ' loop through all tables
        If InStr(1, db.TableDefs(n).Name, "ImportError") > 0 Then
        ' if table is import errors table
            DoCmd.DeleteObject acTable, db.TableDefs(n).Name
            ' delete table
        End If
    Next n

Application.SetOption "Auto compact", True

End Sub

非常感谢任何帮助。谢谢。

1 个答案:

答案 0 :(得分:1)

从我所看到的问题出现在以下几行:

DoCmd.OpenQuery ("5ML")

将其更改为:

accessApp.DoCmd.OpenQuery ("5ML")

详细说明一下:DoCmd-Method来自Access VBA库。因此,您需要一个访问应用程序对象来运行它。您创建了此对象,以便您的代码正常工作但是,当您调用作为访问应用程序一部分的方法而不引用应用程序对象时,您将创建对自动应用程序的全局引用(在本例中为Access)。这就是为什么应用程序不会关闭,即使你最后正确关闭它。那当然是你应该做的事情。因此,您需要做的是首先将应用程序对象放在访问应用程序的每个方法之前,然后再正确关闭应用程序。通常:

accessApp.AMethodOfTheAccessApplication
...
accessApp.CloseCurrentDatabase
accessApp.Quit
Set accessApp = Nothing

这篇文章更清楚,更准确,更详细地解释了这一点:Program won't quit

编辑:要在Excel中运行TableDef-Deletion-Loop,您可以使用以下代码(请注意,您必须同时参考, Microsoft 16.0 Access数据库引擎对象库,以及 Microsoft Access 16.0对象库(版本16并不重要,只需使用这些库的任何最新版本即可你)):

Dim AccessApp As New Access.Application
Dim tdf As DAO.TableDef

AccessApp.OpenCurrentDatabase ("SomeDrive:\SomePath\SomeDb.accdb")

For Each tdf In AccessApp.CurrentDb.TableDefs
' loop through all tables
    If InStr(1, tdf.Name, "tblDelete") > 0 Then
    ' if table is import errors table
        AccessApp.DoCmd.DeleteObject acTable, tdf.Name
        ' delete table
    End If
Next tdf

Set tdf = Nothing

AccessApp.CurrentDb.Close
AccessApp.Quit
Set AccessApp = Nothing

正如您所看到的,我使用了后期绑定而不是早期绑定(用于测试目的)。因此,如果你决定使用早期绑定(比如上面的代码(不用担心引用我猜))你只需要弄清楚如何声明tdf对象。 What does this binding stuff mean?

修改编辑:这是与后期绑定相同的循环:

Dim AccessApp As Object
Set AccessApp = CreateObject("Access.Application")
Dim tdf As Object

AccessApp.OpenCurrentDatabase ("SomeDrive:\SomePath\SomeDb.accdb")

For Each tdf In AccessApp.CurrentDb.TableDefs
' loop through all tables
    If InStr(1, tdf.Name, "tblDelete") > 0 Then
    ' if table is import errors table
        AccessApp.DoCmd.DeleteObject 0, tdf.Name
        ' delete table
    End If
Next tdf

Set tdf = Nothing

AccessApp.CurrentDb.Close
AccessApp.Quit
Set AccessApp = Nothing