Pergunta

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 = ?)

if i specifically use

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')

It returns the value how can i write this query using a user entered value in Cell $A$1 on Sheet1 I've tried the ? in both the Command Text Under Definition AND inside MSQuery under the SQL Statement box.

When using the Command Text Field and the ? I do get a new Parameter Called Parameter1 but when i set the value of Parameter1 to = the cell i get the follow errors:

[Microsoft][ODBC SQL Server Driver]Syntax error or access violation

And

[Microsoft][ODBC SQL Server Driver]Invalid Descriptor Index

even though I make sure the cell value is 555555

Foi útil?

Solução 2

I came up with the following VBA that works super fast and is easy to change.

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

Anytime a new value is entered into Cell A1 the code will automatically change the CommandText (Select Statement).

Also by using the With command you could include many more things such as having it automatically refresh itself after changing parameter by adding

.Refresh BackgroundQuery:=False 

before the End With.

You can change when the CommandText is changed by placing this into a macro assigned to a button or on worksheet refresh or almost an endless amount of variables

Outras dicas

I'm sorry I don't have SQLServer handy to test this, but my guess is that, as Jeff commented, you're passing a Long when a String is expected. Try this

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

I'm not sure if that syntax is right, but essentially you need to put quotes around the question mark. Formatting the cell doesn't work because Excel is just putting the value into the SQL statement where the question mark is. It doesn't evaluate the cell's value and include quotes for strings or hashes for dates or anything like that. Even if the cell value was letters (instead of a string that looks like a number) the SQL wouldn't work because of the missing single quotes.

I think.

Similar to user2140261's solution, use a worksheet_change event to trigger the 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

In the above, $A$1 is the location of the dynamic information (e.g., a date), the SQL table is Table_Name, and the ParameterFlag is the parameter within the SQL code to replace (see below). This is the ChangeParameter function used to change the SQL code:

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

If the desired SQL code were, for example:

SELECT * FROM mytable WHERE startDate > '7/1/2015'

Then this would be edited in the Command Text box to say:

SELECT * FROM mytable WHERE /*<StartDate>*/'7/1/2015'/*</StartDate>*/

And the calling line would be:

.CommandText = ChangeParameter(.CommandText, "StartDate", "'" & Range(Target.Address) & "'")

(the date is stored in the code as a constant, hence the necessity of surrounding the spreadsheet's value with single quotes). All of this works because comments surrounded by /* */ are ignored even if they are in the middle of a line, generally a poor coding practice but useful here.

All places in the original SQL code surrounded by the parameter flags (/*<StartDate>*/ and /*</StartDate>*/ in this case) would be replaced with the new value ("'" & Range(Target.Address) & "'" in this case). The next time the target cell $A$1 is changed, the call will be run again and the parameter changed again without any need to know what its previous value was.

Multiple calls to ChangeParameter could be used for each parameter to be changed, and for each SQL-based table containing parameters to be changed.

Of course, none of this would be necessary if parameter substitution worked for complex code...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top