VBA - 从 Access (QueryTable) 生成 Excel 文件

Posted

技术标签:

【中文标题】VBA - 从 Access (QueryTable) 生成 Excel 文件【英文标题】:VBA - Generate Excel File from Access (QueryTable) 【发布时间】:2012-01-03 17:47:21 【问题描述】:

我有一个项目,其主要目标是生成 Excel(报告),开始使用 VBA 在 Access 中单击按钮。

此报告的内容是存储过程 SQL Server 数据库的结果。

错误行:

With MeuExcel.Worksheets(4)
    .QueryTables.Add connection:=rs, Destination:=.Range("A2")
End With

我得到的是:

invalid procedure call or argument (erro '5')

完整代码(使用 Remou 用户提示编辑):

Sub GeraPlanilhaDT()

Dim MeuExcel As New Excel.Application
Dim wb As New Excel.Workbook

Set MeuExcel = CreateObject("Excel.Application")
MeuExcel.Workbooks.Add

MeuExcel.Visible = True

Dim strNomeServidor, strBaseDados, strProvider, strConeccao, strStoredProcedure As String

strNomeServidor = "m98\DES;"
strBaseDados = "SGLD_POC;"
strProvider = "SQLOLEDB.1;"
strStoredProcedure = "SP_ParametrosLeads_DT"

strConeccao = "Provider=" & strProvider & "Integrated Security=SSPI;Persist Security Info=True;Data Source=" & strNomeServidor & "Initial Catalog=" & strBaseDados

Dim cnt As New ADODB.connection
Dim cmd As New ADODB.command
Dim rs As New ADODB.recordset
Dim prm As New ADODB.parameter

cnt.Open strConeccao

cmd.ActiveConnection = cnt
cmd.CommandType = adCmdStoredProc
cmd.CommandText = strStoredProcedure
cmd.CommandTimeout = 0

Set prm = cmd.CreateParameter("DT", adInteger, adParamInput)
cmd.Parameters.Append prm 
cmd.Parameters("DT").Value = InputBox("Digite o Código DT", "Código do Distribuidor")

Set rs = cmd.Execute()

Dim nomeWorksheetPrincipal As String
nomeWorksheetPrincipal = "Principal"

Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = nomeWorksheetPrincipal



With MeuExcel.Worksheets(4)
    .QueryTables.Add connection:=rs, Destination:=.Range("A2")
End With


cnt.Close
Set rs = Nothing
Set cmd = Nothing
Set strNomeServidor = Nothing
Set strBaseDados = Nothing
Set strProvider = Nothing

If (ActiveSheet.UsedRange.Rows.Count > 1) Then
    FormataDadosTabela
Else
    MsgBox ("Não foi encontrado nenhum Distribuidor com esse DT")
End If


End Sub

奇怪的是,代码在 Excel 中运行时有效,但在 Access 中无效

【问题讨论】:

好的,和你一样,我现在有可以在 Excel 中工作但在 Access 中不工作的代码。添加查询表似乎有问题。我还不明白为什么。我想知道替代解决方案是否适合?例如,将记录简单地写入工作表是否合适? 仅供参考:我已经使用 Access 的 Excel Querytables 自动化多年没有问题,尽管使用 Access 数据作为源。但是,我还没有在 Office 2010 中尝试过。 @Rachel 也许您可以发布一些有效的访问代码? @Remou 我用示例代码更新了我的答案。希望对您有所帮助! 【参考方案1】:

在 Access 中,您需要在 Excel 应用程序对象前加上 Excel 应用程序实例,例如:

With MeuExcel.Worksheets(4).QueryTables.Add( _
    connection:=recordset, _
    Destination:=Range("A2"))
End With

此外,除非您引用 Excel 库,否则 ypu 将需要提供内置 Excel 常量的值。

将对象的名称用于变量是一个非常糟糕的主意。不要说:

Dim recordset As recordset
Set recordset = New recordset

比如说:

Dim rs As recordset

或者更好:

Dim rs As New ADODB.Recordset

如果你有合适的参考。然后您可以跳过 CreateObject。

编辑

提供程序必须是 Access OLEDB 10 提供程序,用于绑定记录集。这适用于我通过 Access 使用 SQL Server 创建数据表:

strConnect = "Provider=Microsoft.Access.OLEDB.10.0;Persist Security Info=True;" _
& "Data Source=XYZ\SQLEXPRESS;Integrated Security=SSPI;" _
& "Initial Catalog=TestDB;Data Provider=SQLOLEDB.1"

【讨论】:

【参考方案2】:

FWIW,有两点很突出:

    正如@Remou 指出的,Excel 引用需要被限定。目前,Range("A2") 不合格。在 Excel 中运行代码时,假定为 ActiveSheet。但是,当从另一个应用程序运行时,该应用程序将在其自己的名为 Range 的库中查找方法或属性,这将在 Microsoft Access 中显示该错误。

    With 块中没有任何代码,因此您可以删除 WithEnd With 关键字;当你这样做时,也删除外部(),像这样:

wb.Worksheets(4).QueryTables.Add Connection:=rs, Destination:=wb.Worksheets(4).Range("A2")

或者,将With 块转移到Worksheet 级别:

With wb.Worksheets(4)
    .QueryTables.Add Connection:=rs, Destination:=.Range("A2")
End With

更新 - 访问 Excel 示例

此示例代码从 Access 自动执行 Excel,创建新工作簿并将 Querytable 添加到第一个工作表。源数据是一个 Access 表。这在 Office 2007 中运行。

Public Sub ExportToExcel()
  Dim appXL As Excel.Application
  Dim wbk As Excel.Workbook
  Dim wst As Excel.Worksheet
  Dim cn As ADODB.Connection
  Dim rs As ADODB.Recordset

  Set appXL = CreateObject("Excel.Application")
  appXL.Visible = True
  Set wbk = appXL.Workbooks.Add
  Set wst = wbk.Worksheets(1)

  Set cn = CurrentProject.AccessConnection
  Set rs = New ADODB.Recordset
  With rs
    Set .ActiveConnection = cn
    .Source = "SELECT * FROM tblTemp"
    .Open
  End With

  With wst
    .QueryTables.Add Connection:=rs, Destination:=.Range("A1")
    .QueryTables(1).Refresh
  End With

End Sub

【讨论】:

无效的过程调用或参数 @Predoff 我修改了我的示例,将Workbook 对象替换为Excel Application 对象。不确定这是否能解决您的问题,但它更正确。 @Rachel 我也尝试过让它工作,我很确定在 Access 中运行存在问题。接受数据的工作表仍然不允许 QueryTables.Add,它失败并出现错误 5,如 Predoff 所述。我使用的示例在 Excel 中运行良好,取自 MSDN。 这与 2010 年完美配合,所以应该是 @Predoff 的解决方案。我必须检查区别在哪里! 它似乎在连接字符串中,但为什么我还没有看到,因为我使用的连接字符串产生了一个完全有效的记录集。【参考方案3】:

您没有说什么 Office 版本,但在 Excel 2007/10 中,QueryTable 是 Listobject 的属性,因此您的代码如下:

With MeuExcel.Worksheets.ListObjects.Add(Connection:=rs, Destination:=Range("A2")).QueryTable

【讨论】:

重新阅读问题后,我意识到这不是问题 - 因为您有运行时错误。我认为@RachelHettinger(和往常一样)一针见血。

以上是关于VBA - 从 Access (QueryTable) 生成 Excel 文件的主要内容,如果未能解决你的问题,请参考以下文章

VBA - 从 Excel 更新 Access 文件的链接表

从 Access 2010 VBA 打开 Excel 2010 文件

使用 VBA 代码从内部复制 Access 数据库

Access 2007 / VBA - 多个表单实例,从模块更新特定实例的控件

使用 VBA 从 Excel 打开和关闭 Access 数据库 - Access 宏错误

MS Access:从 VBA 列出宏