【问题标题】:Passing Parameters into a ListObject QueryTable将参数传递到 ListObject QueryTable
【发布时间】:2022-10-15 03:14:41
【问题描述】:

(来自 Reddit 的交叉发布)我正在尝试使用 VBA 将数据链接自动化到访问查询。不幸的是,查询是查询的查询,所以我不能像往常一样用一个很好的描述性 SQL 语句代替源:/我记录了一个链接不同查询的宏,看看它会是什么样子,然后清理源代码并更改命令文本以引用我想要的查询,但我一直在隐喻地砸键盘试图了解如何添加参数。我需要的只是约会。我已经用谷歌搜索了 2 天,语法让我很困惑。

这就是我得到的,我最近的尝试被注释掉了,文件路径被括号替换了

With ActiveSheet.ListObjects.Add(SourceType:=0, Source:=Array( _
        "OLEDB;Provider=Microsoft.ACE.OLEDB.12.0;Data Source=[]"), _
        Destination:=Range("$A$1")).QueryTable
        .CommandType = xlCmdTable
        .CommandText = Array("PeramIndvCallScore")
        '.Parameters(1).SetParam xlConstant, "8/1/2022"
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .SourceDataFile = []
        .Refresh BackgroundQuery:=False
    End With

我最终会在“查询未运行”、“应用程序/对象定义的错误”、“对象不支持此属性或方法”之间出现不同的运行时错误,(当我从参数)

理想情况下,我希望能够对参数使用单元格范围,以便建立动态数据链接。

有谁知道我是否可以像数据链接一样将 ADO 记录集设置为自动刷新?另外,这里的所有属性都是必需的,还是我可以省略其中的一些? (在那,如果我没有指定,他们是否有默认设置?)

这是SQL:

PeramIndvCallScore:

SELECT CallDetails.CallDate, IIf(([CallTypes].[ID]=1) Or ([calltypes].[ID]=4) Or ([calltypes].[ID]=6),'CSB/VES/Govt',[CallTypes].[Type]) AS CallType, CalculatedScores.TotalScore
FROM CallTypes INNER JOIN (CalculatedScores INNER JOIN CallDetails ON CalculatedScores.KeyID = CallDetails.KeyID) ON CallTypes.ID = CallDetails.CallType
WHERE (((CallDetails.CallDate)=[Date]) AND ((IIf(([CallTypes].[ID]=1) Or ([calltypes].[ID]=4) Or ([calltypes].[ID]=6),'CSB/VES/Govt',[CallTypes].[Type]))='CSB/VES/Govt') AND ((CallDetails.Spanish)=False) AND ((CallDetails.Omit)=False))
UNION ALL SELECT CallDetails.CallDate, IIf(([Calldetails].[Spanish]),'Spanish','') AS CallType, CalculatedScores.TotalScore
FROM CalculatedScores INNER JOIN CallDetails ON CalculatedScores.KeyID = CallDetails.KeyID
WHERE (((CallDetails.CallDate)=[Date]) AND ((IIf(([Calldetails].[Spanish]),'Spanish',''))="CSB/VES/Govt") AND ((CallDetails.Spanish)=True) AND ((CallDetails.Omit)=False));

而且我刚刚再看一眼,发现有一个地方我可以在 SQL 中输入日期作为变量。无论如何,我将需要知道如何为这个项目的其他部分添加参数到 QueryTable 中。任何帮助表示赞赏:)

【问题讨论】:

  • PeramIndvCallScore 是什么?如果 Access 查询可以显示底层 SQL 以及如何使用在日期上听起来像 WHERE 子句的参数?这个日期是如何确定的?
  • 确保限定所有 Range 对象,因为上下文可能会根据活动状态而变化。见How to avoid using Select in Excel VBA
  • @Parfait 我编辑了帖子以包含来自 Access 的 SQL。在这种情况下,范围只是一个空单元格,用作目标

标签: excel vba ms-access listobject


【解决方案1】:

关于您的实施的几个问题:

  • SetParamQueryTable.Parameter 对象的属性。因此,考虑嵌套另一个With 块来初始化QueryTable.Parameter 并调用SetParam

  • 虽然没有明显记录,但参数似乎受 ODBC 驱动程序支持,而不是 OLEDB 提供程序连接。因此,调整为使用 MS Access ODBC 驱动程序。

  • 要使用参数,qmarks,?,必须用于参数占位符而不是命名标识符(提示用户在 MS Access GUI 中输入值)。

  • XlCmdType 不支持保存的查询或后端数据库视图。因此,使用xlCmdSql 类型并从单元格区域或.sql 文件传递​​SQL 字符串。下面显示了 .sql 文件的方法。

SQL

下面另存为 .sql 文件。查询使用表别名和IN 来收紧代码。

SELECT cd.CallDate, 
       IIf((ct.[ID] IN (1, 4 6), 'CSB/VES/Govt', ct.[Type]) AS CallType, 
       cs.TotalScore
FROM CallTypes ct
INNER JOIN (CalculatedScores cs
INNER JOIN CallDetails cd ON cs.KeyID = cd.KeyID) 
  ON ct.ID = cd.CallType
WHERE (((cd.CallDate) = ?) 
  AND ((IIf((ct.[ID] IN (1, 4 6), 'CSB/VES/Govt', ct.[Type])) = 'CSB/VES/Govt') 
  AND ((cd.Spanish)=False) AND ((cd.Omit)=False))

UNION ALL

SELECT cd.CallDate, 
       IIf(([Calldetails].[Spanish]), 'Spanish', '') AS CallType, 
       cs.TotalScore
FROM CalculatedScores cs
INNER JOIN CallDetails cd ON cs.KeyID = cd.KeyID
WHERE (((cd.CallDate) = ?) 
  AND ((IIf(([Calldetails].[Spanish]), 'Spanish', '')) = 'CSB/VES/Govt') 
  AND ((cd.Spanish)=True) AND ((cd.Omit)=False));

VBA

下面读取 .sql 文件,明确限定工作簿对象而不调用 Active,并包含错误处理。请相应地调整文件路径和工作表编号。

Sub BuildQueryTable()
On Error GoTo ErrHandle
    Dim strSQL As String
    
    ' READ .SQL INTO A STRING VARIABLE
    With CreateObject("Scripting.FileSystemObject")
          strSQL = .OpenTextFile("C:PathToMyQuery.sql", 1).readall
    End With

    ' CREATE LIST OBJECT
    ThisWorkbook.Worksheets(1).Columns("A:Z").Delete
    
    With ThisWorkbook.Worksheets(1).ListObjects.Add(SourceType:=0, Source:=Array( _
            "ODBC;Driver={Microsoft Access Driver (*.mdb, *.accdb)};" _
              & "DBQ=C:PathToMyDatabase.accdb"), _
            Destination:=ThisWorkbook.Worksheets(1).Range("A1")).QueryTable
        .CommandType = xlCmdSql
        .CommandText = strSQL
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True

        ' ADD PARAMETER AND SET VALUE
        With .Parameters.Add("prmDate", xlParamTypeDate)
           .SetParam xlConstant, CDate("8/1/2021")
        End With

        'REFRESH QUERY TABLE
        .Refresh BackgroundQuery:=False
    End With
    
ExitHandle:
    Exit Sub
    
ErrHandle:
    MsgBox Err.Number & " - " & Err.Description, vbCritical
    Resume ExitHandle
End Sub

【讨论】:

    猜你喜欢
    • 2017-09-21
    • 2013-01-31
    • 2015-11-03
    • 2016-09-02
    • 2014-07-20
    • 2020-07-28
    • 1970-01-01
    • 2014-01-05
    • 2011-06-13
    相关资源
    最近更新 更多