-1
SELECT Orders.PO_No, Orders.Order_No
FROM DBase.dbo.Orders Orders
Where Orders.PO_No = (Select Top 1 Orders.PO_No From Orders Where Order_No = ?)

如果我特别使用

SELECT Orders.PO_No, Orders.Order_No
FROM DBase.dbo.Orders Orders
Where Orders.PO_No = (Select Top 1 Orders.PO_No From Orders Where Order_No = '555555')

它返回值我如何使用用户在 Sheet1 上的单元格 $A$1 中输入的值编写此查询我试过了?在“定义下的命令文本”和“SQL 语句”框下的 MSQuery 内。

当使用命令文本字段和?我确实得到了一个名为 Parameter1 的新参数,但是当我将 Parameter1 的值设置为 = 单元格时,出现以下错误:

[Microsoft][ODBC SQL Server Driver]语法错误或访问冲突

[Microsoft][ODBC SQL Server Driver]无效的描述符索引

即使我确保单元格值为 555555

4

3 回答 3

0

我想出了以下 VBA,它运行速度超快且易于更改。

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$A$1" Then
        With Range("Table_Query_from_DBase_1[[#Headers],[PO_No]]").ListObject.QueryTable
        .CommandText = Array( _
        "SELECT Orders.PO_No, Orders.Order_No" & Chr(13) & "" & Chr(10) & "FROM DBase.dbo.Orders Orders" & Chr(13) & "" & Chr(10) & "Where Orders.PO_No =(Select Top 1 Orders.PO_No From Orders Where Order_No = '" & Range("A1").Value & "')" _
                   )
        End With
    End If
End Sub

每当在单元格 A1 中输入新值时,代码将自动更改 CommandText(选择语句)。

此外,通过使用 With 命令,您可以包含更多内容,例如通过添加更改参数后使其自动刷新

.Refresh BackgroundQuery:=False 

结束前。

您可以通过将其放入分配给按钮或工作表刷新或几乎无穷无尽的变量的宏中来更改 CommandText 何时更改

于 2013-03-06T17:09:44.163 回答
0

很抱歉,我没有方便的 SQLServer 来测试它,但我的猜测是,正如 Jeff 评论的那样,当需要一个 String 时,你会传递一个 Long 。尝试这个

Where Orders.PO_No = (Select Top 1 Orders.PO_No From Orders Where Order_No = "'" & ? & "'")

我不确定语法是否正确,但本质上您需要在问号周围加上引号。格式化单元格不起作用,因为 Excel 只是将值放入问号所在的 SQL 语句中。它不评估单元格的值,并包括字符串的引号或日期的哈希值或类似的东西。即使单元格值是字母(而不是看起来像数字的字符串),SQL 也不会工作,因为缺少单引号。

我认为。

于 2013-03-06T15:37:46.403 回答
0

类似于 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 的表。

当然,如果参数替换适用于复杂代码,则这些都不是必需的......

于 2016-05-31T23:06:52.193 回答