I would like to use an Excel cell to change the reference data in a Where statement so that I don't have to keep going into power query to change the statement.
Instead of the 31690 in the below code I would like to reference cell B7 in sheet1 of the same Workbook instead.
Is this possible? and if so how?
Thanks in advance.
WHERE ORDERDATE >= #Month13#(lf)#(tab)and STOCKCODE is not null#(lf)#(tab)AND SALESORD_HDR.ACCNO = '31690'
Maybe something like this?
For this approach to work, you need to make sure your spreadsheet has a table and the table's range starts with A1 and spans beyond the cell with the value in it--in this case, B7. Here's an example:
I started by creating this spreadsheet with a table named Table1:
Then, I used Table1 as the source in Power Query.
Notice that with the table above, what was row 7 is row 6. This is because the column headers don't have row numbers in Power Query. This change in row numbering matters for finding your targeted cell.
Then I added some custom M code. This code first extracts the second column's name from the list of column names. (Because the second column would be column B of the spreadsheet.) Then it uses that second column's name to create a table of that column's values, from which it then extracts the sixth row entry. (Because that sixth row entry would be the seventh row entry in the spreadsheet.) Note that the {1} points to the second column and the {5} points to the sixth row. That's because Power Query indexing starts at 0.
I went into Advanced Editor and renamed the step from Custom to DateVariable:
DateVariable = Table.Column(Table1_Table, Table.ColumnNames(Table1_Table){1}){5},
Then I added some more custom M code to concatenate the DateVarable with the rest of your SQL statement as an example:
Here's my M code:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
DateVariable = Table.Column(Source, Table.ColumnNames(Source){1}){5},
SQL_Statement = "WHERE ORDERDATE >= #Month13#(lf)#(tab)and STOCKCODE is not null#(lf)#(tab)AND SALESORD_HDR.ACCNO = '" & Text.From(DateVariable) &"'"
in
SQL_Statement
Simple solution using a named range
First, select cell B7 and enter a name in the Name Box (e.g. CellReference). Then right-click on the cell and click on Get Data from Table/Range.
This opens the Power Query Editor with a query that returns a table containing the cell from the named range. Open the advanced editor, delete the entire content of the query and type Text.From(Excel.CurrentWorkbook(){[Name="CellReference"]}[Content][Column1]{0}) and click on Done, this is what it should look like:
Note: Text.From() is used so that value returned by CellReference can be concatenated with the SQL query using &. Also, this function is preferable to Number.ToText() which does not work with text values.
Finally, insert the query name in your SQL query: WHERE ORDERDATE >= #Month13#(lf)#(tab)and STOCKCODE is not null#(lf)#(tab)AND SALESORD_HDR.ACCNO = "&CellReference
Note that if the cell contained a text value instead, then you would need to adjust the syntax like this: ... SALESORD_HDR.ACCNO = '"&CellReference_Text&"'"
How to deal with warnings: new query permission and Formula.Firewall
How to give permission to run all new native database queries
Depending on your Query Options settings, you may get this warning message regarding the permission to run the modified SQL query each time CellReference contains a new value:
If you are certain that the cell will never contain a string of characters that could modify the database, you can disable this warning message by going to File -> Options and settings -> Query Options. Under GLOBAL, go to Security and uncheck Require user approval for new native database queries.
Note that this is a global setting that is immediately applied to all your Excel files, including those that are currently open.
How to disable the Formula.Firewall warning message
Depending on your Privacy Levels settings, you may get a Formula.Firewall warning message preventing the query from being executed:
If you are in a situation where you can disregard privacy levels, you can disable this message by going to File -> Options and settings -> Query Options. Under CURRENT WORKBOOK, go to Privacy and select Ignore the Privacy Levels and potentially improve performance.
Click on OK and refresh the query.
If, on the other hand, your workbook needs to preserve a privacy level of Private or Organizational, to my knowledge there is currently no way of integrating CellReference to a SQL query (even using a SQL parameter set with the Value.NativeQuery function or a Power Query Parameter ) without raising this warning message. The only solution would be to include CellReference in another step in the query, but then the filtering will occur in Power Query and not at the server level: query folding is interrupted when a step includes a query/function/parameter that is linked to an external data source including a named range in the workbook itself.
If your workbook privacy level is set to Public, you should be able to avoid this warning message by using the Value.NativeQuery function (you can even enable query folding for further query steps if you are using a SQL Server or PostgreSQL database). If you still get the warning message, you can try combining the two queries accessing each data source (the database and the worksheet) into a single query.
Note: these steps were tested with Excel Microsoft 365 (Version 2107) on Windows 10 64-bit connected to a local SQL Server 2019 (15.x) database.
This answer was prepared by referring to many blog posts by Chris Webb (linked above) and by Ken Puls (like this one).
Related
I have defined a table Table1 in source file.xlsx. When source file.xlsx is open, in target file.xlsx, I could use ='source file.xlsx'!Table1[#Data] in a cell to get the table data.
However, I realise that if I close source file.xlsx, that formula becomes ='\\Mac\Home\Downloads\source file.xlsx'!Table1[#Data] and its value becomes #REF!.
This is not the case for an external reference (link) to a cell range in another workbook; an external reference to a cell/range could still get value when the source file is closed.
Could anyone tell me how to update the table data even though when the source file is closed?
This is expected behaviour
From the Microsoft Help
Links to data tables residing in external files display #REF!
Symptoms
Consider the following scenario:
You insert a table in an Excel file, named for example source.xlsx.
In another file, named for example destination.xlsx, you insert a link to the data table which resides in source.xlsx.
You close both source.xlsx and destination.xlsx.
You open destination.xlsx and you choose to update links when prompted.
Result: the cells that are linked to the external data table display #REF!.
Cause
This is expected behavior for Excel.
New references to external workbooks that aren’t open will successfully parse without verifying the reference, but will return #REF.
When loading an external structure reference to a closed workbook, the reference is not updated by default. If you choose to calculate the formula the result is #REF! instead of the corresponding value.
Microsoft Help
As an alternative, create a query to the table. This can be refreshed from a closed workbook
To answer your question:
What you are seeing is how excel works at a cell formula level. If you type in
=[file.xlsx]Sheet1!Table1[#All]
This might be a little more of what you want, but it will give you the whole table.
For one column you can do:
=file.xlsx!Table1[[#Headers],[Date]]
=file.xlsx!Table1[Date]
You can create a defined name for Table1 as mytable then you would enter the formula =file.xlsx!mytable
All the above becomes similar to ='\\Mac\Home\Downloads\source file.xlsx'!Table1[#Data]
For an alternate method (recommended):
The very best way I have found to do this is using power query. This is not formulas in cells but it is like a database query tool. There are several people on You-tube making videos about using power query for this exact thing. I will step you through the process starting in the file where you want the data to appear. Go to:
Data > (Get & trasform Data) Get Data> From File> From Workbook...
In the popup window navigate to your file "\Mac\Home\Downloads\source file.xlsx" and click Import.
In the next window choose "Table1" (or an item that you want).
Now choose load and this data loads into your sheet.
If you want to transform the data of "Table1" then...
Data > Queries & Connections> (this pops open a "Queries & Connections")
Right click on Table1 then edit.
There are many options to choose from such as: remove columns, filter...
To calculate new columns use > Add Column which uses M function.
For Vlookup use Merge Queries,
For a Count, Sum, Average, or ... of rows (utilizing one or multiple columns) use "Group by".
After you "Close & Load" the table gets updated. If new values get entered into file.xlsx Table1, refresh the power query table and the data shows up.
I have an Excel SQL query made using the Query wizard / power query. Sometimes, when I refresh the data, the columns shuffle order! I have already tried checking/unchecking "preserve column sort" as suggested here: https://www.mrexcel.com/board/threads/sql-changing-column-order-when-put-into-excel.207385/
#Nathan brings up a good point. Try specifying in the query itself, the order of the columns.
If that does not work, The solution would be to accomodate the different order of columns as a possible outcome every time by making the result query into a ListObject Table. (I believe you can check this as part of the Query Wizard, to import as Table)
Then you can use the name of the columns without knowing the range address in your worksheet formulas and VBA code. You could simply refer to the column name in the format shown in this tutorial, then get the properties for column or row number using any number of methods.
Tutorial on using ListObject Tables
scenario:
Running an XL sheet, using a single powerquery to retrieve data from a SQL server. The resulting dataset gets used in two subqueries. All three datasets are then loaded to pivot tables in the XL sheet.
objective:
Send query using 2 parameters retrieved from XL sheet, thereby reducing size of returned dataset. Folding query back onto SQL server, rather than filter post-retrieval in PQ.
description of problem:
if I use the below configuration for the main query:
let
dbQuery = "SELECT * FROM dbo.somequery",
Source = Sql.Database("<server>", "<database>", [Query=dbQuery])
in
Source
This works fine and returns about 6500 rows almost instantly.
The following function is defined as 'GetRange' in PQ to retrieve a cell value:
(rangeName) =>
Excel.CurrentWorkbook(){[Name=rangeName]}[Content]{0}[Column1]
Two parameters get retrieved by using below syntax for each:
= GetRange("<named cell>")
If I now change the dbQuery to:
dbQuery = "SELECT * FROM dbo.xlPAS_PivotOutput
WHERE parameter1=" & Text.From(parameter1) & " and parameter2=" & Text.From(parameter2),
The query does compile, and results are returned, but Excel PQ takes about 1 to 2 minutes to actually return a value?
It appears that simply retrieving the 2 cell values and using them as input parameters takes a huge effort for some reason ?
I've been trying to debug a query that was pulling in data from a URL that I pick up from a cell in the spreadsheet. It was running ridiculously slowly, whereas using the URL explicitly in the query was running fine. I kept trying to simplify the spreadsheet to troubleshoot up to the point I had a query that was just selecting the text value from a single cell in an otherwise empty spreadsheet and this was still slow as hell.
The Name Manager revealed that there were a couple of invalid name references and one referencing a range in another Excel file on another location which I couldn't access. Deleting these obsolete names seem to have fixed the problem.
The fact that name references that are unused in the spreadsheet cause this type of problem is definitely an Excel bug, but at least knowing this, searching for invalid name references and deleting them seems to fix the problem.
I have an Excel spreadsheet like this:
Where the Student Name, Student ID and Classification are, I would like to fill that with the results from a SQL Server view. The columns to the right (Capstone, Milestone 2, Milestone 1, Benchmark, Semester Grade, Notes) will remain blank until the instructor fills them in later. These columns will not be written back to the database but will be saved, with the data that is loaded from the database, into the first three columns in it's Excel spreadsheet format.
Question 1: Is there a way to simply "embed" the data that is coming from the view?
Question 2: If not, can you provide a link to an example using a macro to read records and insert them (moving lower rows down with each new record)?
TIA
On the Data tab in Excel you can select "From Other Sources" icon from the "Get External Data" group to pull your student data from a SQL Server view.
That will give you the "embedded" data, until you decide to Refresh your connection and retrieve updated data from the view.
EDIT:
Use the CopyFromRecordset method for Range objects. Here is the link that provides working examples for what you are trying to accopmlish, without the range being being pushed to the side. Entries #3 and #11 provide the VBA examples.
http://www.xtremevbtalk.com/showthread.php?t=217783
You will need to use VBA to create an ADO connection, recordset, command, and parameter.
Dim adostudent as ADODB. (...) ^ use the above
Then, assign a named range to the areas that you would like to drop the information
StudentRow
Then, use a Do Until and an iterator and do until.eof and .movenext to drop the values from the recordset into the range.
irow = 10 'insert the header row # + 1here
Do Until adostudent.EOF = True
with adostudent
StudentRow(irow,1).value =.Fields("Student Name").value
...
...
.movenext
irow = irow + 1
loop
You can use the Data->Get External Data->From Other sources->From SQL feature in Excel.
Or use my Add-In:
http://blog.tkacprow.pl/excel-sql-add-in-free/
I would love to know how to import a single value from my Access database into an Excel cell.
Alternatively removing the header would be a good start.
The query
SELECT SUM(DEMANDS) AS TOTAL FROM [DB PROD]
gives me a header named TOTAL and, right below it, the sum I'm interested in. I use this query from within Excel (Data > Get External Data > From Access). How can I only get the sum in a single Excel cell?
One way to accomplish your goal would be to put your existing query on a different Sheet, say Sheet2, so the column header appears in Sheet2!A1 and the value appears in Sheet2!A2. Then reference the value cell from elsewhere in the Excel document. (The formula will look something like =Table_test.accdb[TOTAL].)
If you had several queries you could presumably keep them together (side by side) on the same sheet. You could also hide the query sheet so the "magic" would be more transparent to the user.
I am not sure I understand what you are doing, but, in order to read Access data from Excel, you need to do the following:
programmaticaly open a connexion in your Excel code, pointing to your
access database (let's say an ADO connexion for example)
then execute your 'SELECT' through this connection, using the ADODB.command object. That will return the requested value
another option would be to open a local recordset in Excel,based on your SQL intruction, and read the value.
Then do not forget to close your connexion