Запустить запросы доступа из Excel VBA - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь написать макрос в Excel VBA, который просто открывает базу данных доступа и выполняет 2 запроса в доступе. Кажется, он работает и выполняет запросы каждые 2 нажатия кнопки макроса. Я имею в виду, что я щелкаю по нему, он работает, при втором щелчке я получаю «ошибку времени выполнения 462» при втором щелчке, при третьем щелчке он работает, при четвертом щелчке я снова получаю сообщение об ошибке и так далее. Я не могу понять, почему это так. Вот код ниже.

Sub QueryAccess1()

Dim db As Access.Application
Set db = New Access.Application
'set variables

db.Visible = True

db.OpenCurrentDatabase ("DatabaseFileName")
'open database

'--------------------------------------------------------------
On Error Resume Next

db.DoCmd.DeleteObject acTable, "TableName"
'if the table does not exist it skips this line
'--------------------------------------------------------------

On Error GoTo 0
'sets the error back to normal

'--------------------------------------------------------------
CurrentDb.Openrecordset ("QUERY1")
CurrentDb.Execute ("QUERY2")
'Calls the queries
'--------------------------------------------------------------

'--------------------------------------------------------------
db.CloseCurrentDatabase
db.Quit
'Closes Access
'--------------------------------------------------------------

Set db = Nothing

End Sub

Когда я получаю ошибку, я получаю ее на линии

CurrentDb.Openrecordset ("QUERY1")

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Мне удалось заставить его работать по методу Парфе.Вот что у меня есть.

Sub QueryAccess1()

Dim conn As Object, rst As Object
Dim path As String


Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")

path = Sheets("SheetName").Range("A1")

'OPEN CONNECTION
conn.Open ConnectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & path

'DELETES TABLE CONTENTS
conn.Execute "DELETE FROM [Table1]"

'RUN UNION QUERY AND INSERT INTO TABLE
rst.Open "SELECT * FROM [Query1]", conn
conn.Execute "INSERT INTO [Table1]  select * from [QUERY1] "

Set rst = Nothing: Set conn = Nothing

End Sub
0 голосов
/ 16 мая 2018

Вероятно, ошибка каждые два клика связана с открытием только что удаленной таблицы, где бы она ни находилась. Рассмотрите возможность перебора коллекции MS Access TableDefs , чтобы условно удалить объект, если он существует. Затем измените порядок выполнения запроса действий перед вызовом OpenRecordset .

Public Sub RunQueries()
On Error Goto ErrHandle:
    ' DAO REQUIRES REFERENCE TO Microsoft Office X.X Access Database Engine Object Library
    Dim tbl As DAO.TableDef     
    Dim rs As DAO.Recordset
    Dim db As New Access.Application

    db.Visible = False                   ' KEEP DATABASE RUNNING IN BACKGROUND

    For Each tbl in db.CurrentDb.TableDefs
        If tbl.Name = "TableName" Then
            db.DoCmd.DeleteObject acTable, "TableName"
        End If
    Next tbl

    ' ASSUMED AN ACTION QUERY
    db.CurrentDb.Execute "QUERY2", dbFailOnError

    ' ASSUMED A SELECT QUERY BUT CALL BELOW IS REDUNDANT AS IT IS NEVER USED
    Set rs = db.CurrentDb.OpenRecordset("QUERY1")   

ExitHandle:
    ' FREE RESOURCES
    Set rst = Nothing: Set conn = Nothing
    db.CloseCurrentDatabase
    db.Quit
    Set db = Nothing
    Exit Sub

ErrHandle:
    MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
    Resume ExitHandle
End Sub

В сторону - никогда не используйте On Error Resume Next в VBA. Всегда заранее предвидеть и обрабатывать исключения.


В качестве альтернативы, вместо использования команды make-table SELECT * INTO и необходимости программного удаления таблицы, просто создайте таблицу один раз , а затем используйте DELETE и INSERT, которые могут бегать каждый раз. Конечно, это предполагает, что структура таблицы (поля / типы) остается прежней.

DELETE FROM myTable;

INSERT INTO myTable (Col1, Col2, Col3) 
SELECT Col1, Col2, Col3 FROM myOtherTable;

SELECT * FROM myTable;

Наконец, нет никаких оснований даже использовать библиотеку объектов MS Access для открытия / закрытия .GUI только для выполнения запросов. Поскольку Access - это база данных, подключитесь к ней, как к любому другому бэкэнду (например, SQLite, Postgres, Oracle), и выполняйте ваши запросы оттуда. Ниже приведен пример подключения ODBC, драйвер которого можно легко заменить на драйверы других RBDMS.

Dim conn As Object, rst As Object

Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")

' OPEN CONNECTION
conn.Open "DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};" _
            & "DBQ=C:\Path\To\Access\DB.accdb;"

' RUN ACTION QUERIES
conn.Execute "DELETE FROM myTable"
conn.Execute "INSERT INTO myTable (Col1, Col2, Col3)" _
               & " SELECT Col1, Col2, Col3 FROM myOtherTable"

' OPEN RECORDSET
rst.Open "SELECT * FROM myQuery", conn

' OUTPUT TO WORKSHEET
Worksheets("DATA").Range("A1").CopyFromRecordset rst
rst.Close

Фактически, вышеупомянутый подход даже не требует установленного MS Access GUI .exe! Кроме того, обязательно сохраняйте запрос SELECT (даже один внутри INSERT) внутри Access и не запускайте его как строку SQL VBA, поскольку механизм доступа сохранит лучший план выполнения для сохраненных запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...