类似于 user2140261 的解决方案,使用 worksheet_change 事件来触发更改:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" Then
With ActiveSheet.Range("Table_Name").ListObject.QueryTable
.CommandText = ChangeParameter(.CommandText, "ParameterFlag", Range(Target.Address))
End With
ActiveWorkbook.RefreshAll
End If
End Sub
上面的$A$1是动态信息的位置(比如一个日期),SQL表是Table_Name,ParameterFlag是SQL代码中要替换的参数(见下文)。这是用于更改 SQL 代码的 ChangeParameter 函数:
Function ChangeParameter(src As String, parameter As String, newValue As String)
'Replace src text surrounded by startParameter and endParameter with newValue
Dim startPosn As Long, endPosn As Long
Dim startParameter As String, endParameter As String
startParameter = "/*<" & parameter & ">*/"
endParameter = "/*</" & parameter & ">*/"
startPosn = 0
Do
startPosn = InStr(startPosn + 1, src, startParameter)
If startPosn Then
endPosn = InStr(startPosn + Len(startParameter), src, endParameter)
If endPosn Then
src = Left(src, startPosn + Len(startParameter) - 1) & newValue & Mid(src, endPosn)
Else
Exit Do
End If
End If
Loop While startPosn
ChangeParameter = src
End Function
例如,如果所需的 SQL 代码是:
SELECT * FROM mytable WHERE startDate > '7/1/2015'
然后这将在命令文本框中编辑为:
SELECT * FROM mytable WHERE /*<StartDate>*/'7/1/2015'/*</StartDate>*/
调用线路是:
.CommandText = ChangeParameter(.CommandText, "StartDate", "'" & Range(Target.Address) & "'")
(日期作为常量存储在代码中,因此有必要用单引号将电子表格的值括起来)。所有这些都有效,因为被包围的注释/* */
即使在一行的中间也会被忽略,这通常是一种糟糕的编码实践,但在这里很有用。
/*<StartDate>*/
原始 SQL 代码中由参数标志(在本例中)包围的所有位置/*</StartDate>*/
都将替换为新值(在本例中为"'" & Range(Target.Address) & "'")。下次更改目标单元格 $A$1 时,将再次运行调用并再次更改参数,而无需知道其先前的值是什么。
对 ChangeParameter 的多次调用可用于每个要更改的参数,以及每个包含要更改的参数的基于 SQL 的表。
当然,如果参数替换适用于复杂代码,则这些都不是必需的......