4

I have a workbook where I fetch data from SQL Server using fixed parameter values for a SQL query.

I want to make another sheet and have the parameter for the SQL query be taken from the cell values.

I didn't find anything on this regard.

Also I would like to refresh the data as soon as the cell values changes in the other sheet.

1
  • I had difficulty finding the answer to this same question when I was first looking for it, as well. I think it's generally more advised to, when possible, run the query for the data without the variable restrictions, and then limit the data once it's in PowerQuery. There have been times when I've gotten a warning from PQ about refreshing a query with this type of setup..... Commented Apr 4, 2018 at 18:22

1 Answer 1

9

For this to work, you need to set up three different parts:

1) A parameter table in an Excel sheet

2) Changes to the advanced editor in PowerQuery

3) A macro to refresh the PQ when any cells in the parameter table are changed


1) Excel Table

You can see I included a column called param which can hold a Parameter name to help keep straight which parameter is which.

Sample Param Table


2) PQ Advanced Editor

let
    ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Param = "'" & Text.From(ParamTable[value]{0}) & "'",
    Source = Sql.Database("IP Address", "Database Name", [Query="Select * from weeks#(lf)where date >= '2018-01-01' and date < " &Param])
in
    Source

Equivalent alternative: (Difference in location of variable used in SQL query.)

let
    ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Param = "'" & Text.From(ParamTable[value]{0}) & "'",
    Source = Sql.Database("IP Address", "Database Name", [Query="Select * from weeks#(lf)where date < " &Param & " and date >= '2018-01-01'"])
in
    Source

Alternative Variable Type: (If dealing with numbers, the string markers ' aren't required)

let
    ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Param = Text.From(ParamTable[value]{0}),
    Source = Sql.Database("IP Address", "Database Name", [Query="Select * from weeks#(lf)where cnt < " &Param & " and date >= '2018-01-01'"])
in
    Source

Explanation:

After pulling the Parameter Table into the PQ Query (ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content]), the columns can be accessed by column name [value] and the rows by a zero-index number {0}. Since I was pulling in a date-value. I needed to convert it to a string value I could insert into the SQL Query -- thus the Text.From() and the appended ''s to the ends (SQL marks strings with single ' rather than the double ")

Since I named the variable Param, to use it in the string, I substituted &Param for the value which had originally been there.


2.1 Power Query's Value.NativeQuery

let
    ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Param = ParamTable[value]{0},
    Source = Value.NativeQuery(Sql.Database("IP Address", "Database Name"), "Select * from weeks where date < @dateSel and date >= '2018-01-01'",[dateSel = Param])
in
    Source

Alternative Formatting:

let
    ParamTable = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Param = ParamTable[value]{0},
    Source = Sql.Database("IP Address", "Database Name"),
    Data = Value.NativeQuery(Source, "

Select * from weeks
where date < @dateSel and date >= '2018-01-01'

",[dateSel = Param])
in
    Source

Notes:

When using Value.NativeQuery(), you can pass a date or datetime value directly in as a variable without having to include the single apostrophes.

Sometimes splitting the data retrieval into a Source step and a NativeQuery step can help with PQ's sporadic firewall issues.


3) Macro

This works for a simple check if anything in the table has changed, then runs the refresh. You will need to make sure this is placed in the correct module. Items you will need to change are:

  • Sheet1 is the codename of the worksheet with the parameter table.
  • "Table" is the name of the Parameter table
  • "Query - Query1" is the name of the connection to be refreshed

Note: Query1 is the name of the query. Default names for connections are usually Query - & query name

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Sheet1.ListObjects("Table1").DataBodyRange) Is Nothing Then
        ThisWorkbook.Connections("Query - Query1").Refresh
    End If
End Sub
Sign up to request clarification or add additional context in comments.

6 Comments

Do you know how to get to the general query editor? Once there, go to the "View" tab, then you should see an "Advanced Editor" button second from the right. The button on the very right is the "Query Dependencies" button which is also semi-useful.
I'm getting a cyclic reference was encountered during evaluation error when I paste the power query in the advanced editor. Can you help?
I can try. Could you show me the code you have in your Advanced Editor? Also, just clarifying, that for Part 2), what I posted is really just an example of how it would look with the param line added, and the variable substitution in place.
Sure. let Client_UID = "'" & Text.From(Table1[value]{0}) & "'", Year = "'" & Text.From(Table1[value]{1}) & "'", Period = "'" & Text.From(Table1[value]{2}) & "'", Source = Sql.Database("0.0.0.0", "TestDB", [Query="EXEC [sp_sprocname] @Client_UID = " &Client_UID & ", @Year = " &Year & ", @Period = " &Period & ", @Trans = '123'"]) in Source
First, I just want to point out that of @Year is not supposed to be a SQL string (i.e. SQL is expecting an integer or double) you should change Year = "'" & Text.From(Table1[value]{1}) & "'" to Year = Text.From(Table1[value]{1}) Also, same with any other value SQL is not expecting a string for.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.