Запустите Excel VBA в Access - PullRequest
0 голосов
/ 24 января 2020

Я много занимался этим и не нахожу никаких примеров того, как это будет работать.

Я написал код в Excel, который хочу запустить в MS Access. Я вставил код для запуска в Access.

Все примеры или информация, которые я нашел, относится к 2003 Access. Я использую Access 2016.

Код Excel

Public Function getworkbook()
    ' Get workbook...
    Dim ws As Worksheet
    Dim Filter As String
    Dim targetWorkbook As Workbook, wb As Workbook
    Dim Ret As Variant

    Application.DisplayAlerts = False

    Sheets("DATA").Delete
    '   Sheets("DATA").Cells.Clear

    Set targetWorkbook = Application.ActiveWorkbook

    ' get the customer workbook
    Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
    Caption = "Please Select an input file "
    Ret = Application.GetOpenFilename(Filter, , Caption)

    If Ret = False Then Exit Function

    Set wb = Workbooks.Open(Ret)

    wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)

    ' ActiveSheet.Paste = "DATA"

    ActiveSheet.Name = "DATA"

    ThisWorkbook.RefreshAll

    ' Application.Quit
    Application.DisplayAlerts = True

End Function

Код, который я нашел и попытался использовать в Access.

Public Function runExcelMacro(wkbookPath)
    Dim XL As Object
    Set XL = CreateObject("Excel.Application")
    With XL
        .Visible = False
        .displayalerts = False
        .Workbooks.Open wkbookPath
        'Write your Excel formatting, the line below is an example
        .Range("C2").value = "=1+2"
        .ActiveWorkbook.Close (True)
        .Quit
    End With
    Set XL = Nothing
End Function

Ответы [ 2 ]

1 голос
/ 24 января 2020

Есть несколько концепций, с которыми вам нужно разобраться в первую очередь.

Библиотечные ссылки и область применения

Ваш оригинальный код был написан в Excel. Поэтому в этом проекте VBA на него ссылается объект Excel. В вашем проекте Access VBA на него нет ссылок. Вы можете сравнить это, посмотрев на Tools -> References.

. Это подводит нас к понятию «раннее связывание» и «позднее связывание». Когда вы набираете что-то вроде Range., вы получаете IntelliSense VBA, чтобы сообщить вам, что вы можете сделать с Range или чем-то еще. Но в Access у вас нет библиотеки объектов Excel, на которую есть ссылки по умолчанию. Следовательно, Range. не даст intellisense и , вы не можете запустить код, потому что Access не имеет Range в своей объектной модели, и ваш проект VBA, скорее всего, не имеет ссылки, которая имеет его .

Следовательно, ваш код должен быть настроен для запуска с поздним связыванием, если вы не хотите добавлять ссылку на объектную модель Excel, и вы, скорее всего, хотите этого в любом случае.

Неполная ссылка

Ваш исходный код Excel содержит неквалифицированные ссылки на различные глобальные объекты, доступные в объектной модели Excel.

Application.DisplayAlerts = False
...
Sheets("DATA").Delete
...
Set wb = Workbooks.Open(Ret)
...

Они не обязательно будут работать согласованно в проектах VBA, размещенных на других хостах, кроме Excel и наверняка не будет работать в позднем коде. Кроме того, если вы решите добавить ссылку на объектную модель Excel, у вас все равно останется утечка экземпляра Excel, что может привести к появлению призрачных экземпляров, поскольку неквалифицированные ссылки на глобальные объекты неявно создадут экземпляр Excel, с которым вы не сможете взаимодействовать и который также может вызвать другая ошибка времени выполнения по пути. Чтобы сделать ваш код более привязываемым позднее, вам нужно что-то вроде:

Set ExcelApp = CreateObject("Excel.Application")

ExcelApp.DisplayAlerts = False
...
Set MyBook = ExcelApp.Workbooks("Whatever")
MyBook.Sheets("DATA").Delete
...
Set wb = ExcelApp.Workbooks.Open(Ret)
...

Обратите внимание, что все глобальные объекты, к которым вы могли получить доступ в контексте, размещенном в Excel, теперь должны быть самостоятельными переменными. Кроме того, у вас не будет доступа к ThisWorkbook или даже Sheet1 в других проектах VBA, поскольку Excel больше не является хостом. Вы должны соответственно отрегулировать.

Переключение между ранним и поздним связыванием

Код с ранним связыванием упрощает разработку, поскольку вы получаете полноценный браузер intelisense и объектов, помогающий вам написать код. Однако при обращении к другим объектным моделям вы можете распространять свой код VBA с использованием позднего связывания, чтобы избежать проблем с версиями и неработающих ссылок. Но вы можете получить лучшее из обоих миров:

#Const EarlyBind = 1

#If EarlyBind Then
Dim ExcelApp As Excel.Application
#Else
Dim ExcelApp As Object
#End If

Set ExcelApp = CreateObject("Excel.Application")

Это иллюстрирует использование аргумента условной компиляции , чтобы позволить вам иметь ExcelApp переменную, которая может быть либо Excel.Application (иначе ранний предел) против Object (он же поздний предел). Для изменения просто измените строку Const LateBind между 0 или 1.

0 голосов
/ 24 января 2020

Сначала уточним терминологию:

  • VBA - это отдельный язык, не привязанный к любому приложению MS Office. В разделе Инструменты \ Ссылки вы увидите, что Visual Basi c для приложений обычно является первым проверенным объектом. Чем отличается запуск VBA в Excel, Access, Word, Outlook и т. Д. c. это доступ по умолчанию к их объектной библиотеке. В частности:

    • Только Excel видит Рабочая книга , Рабочая таблица , et c. без определения его источника
    • Только Доступ видит Формы , Отчеты и др. c. без определения источника
    • Только Слово видит Документы , Абзацы , et c. без определения его источника
  • При запуске библиотеки сторонних объектов внутри приложения, например, MS Access, обращающегося к объектам Excel, вы должны определить и инициализировать сторонние объекты посредством ссылки либо с ранним или позднее связывание:

    ' EARLY BINDING, REQUIRES EXCEL OFFICE LIBRARY UNDER REFERENCES
    Dim xlApp As Excel.Application
    Dim wb As Excel.Workbook
    Dim ws As Excel.Worksheet
    
    Set xlApp = New Excel.Application
    Set wb = xlApp.Workbooks.Open(...)
    Set ws = wb.Worksheets(1)    
    
    
    ' LATE BINDING, DOES NOT REQUIRE EXCEL OFFICE LIBRARY UNDER REFERENCES
    Dim xlApp As Object, wb As Object, ws As Object
    
    Set xlApp = CreateObject("Excel.Application")
    Set wb = xlApp.Workbooks.Open(...)
    Set ws = wb.Worksheets(1)  
    

С учетом сказанного просто оставьте исходный код почти без изменений, но измените определения и инициализации. Примечательно, что все вызовы Application теперь указывают на объект Excel.Application, и их не следует путать с приложением Access. Кроме того, рекомендуется избегать использования .Select/ .Activate/ Selection/ ActiveCell/ ActiveSheet/ ActiveWorkbook.

Public Function getworkbook()
    ' Get workbook...
    Dim xlApp As Object, targetWorkbook As Object, wb As Object, ws As Object         
    Dim Filter As String, Caption As String
    Dim Ret As Variant

    Set xlApp = CreateObject("Excel.Application")
    Set targetWorkbook = xlApp.Workbooks.Open("C:\Path\To\Workbook.xlsx")

    xlApp.DisplayAlerts = False

    targetWorkbook.Sheets("DATA").Delete

    ' get the customer workbook
    Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
    Caption = "Please Select an input file "
    Ret = xlApp.GetOpenFilename(Filter, , Caption)

    If Ret = False Then Exit Function    
    Set wb = xlApp.Workbooks.Open(Ret)

    wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)    
    Set ws = targetWorkbook.Worksheets(targetWorkbook.Sheets.Count)
    ws.Name = "DATA"

    targetWorkbook.RefreshAll

    xlApp.DisplayAlerts = True
    xlApp.Visible = True                        ' LAUNCH EXCEL APP TO SCREEN
    ' xlApp.Quit

    ' RELEASE RESOURCEES
    Set ws = Nothing: Set wb = Nothing: Set targetWorkbook = Nothing: Set xlApp = Nothing
End Function

. Кстати, вышеизложенное может быть запущено в любом приложении MS Office как объект-родитель приложение (здесь MS Access) используется!

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