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/
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 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).
Hi I am trying to load table records of a power query table to my Excel Workbook.
I have this transformed table in Power Query wherein Table in the Records column are table objects that contains data fetched from a REST endpoint.
I want to load the Tables to worksheets which I will be naming based on the WorksheetName column.
I have a worksheet that will contain the payload for the request and in the VBA which will be triggered by a click of a button, the Worksheet creation + population will occur.
Is there a way of doing that in VBA? I tried searching for a comprehensive way of doing that but I cant find any.
Thank you very much.
Are the sheetnames variable based on userinput? I had a similar issue, I just created the sheets, loaded the query to them and removed all but the first two rows (to prevent the file not getting slow).
Then when a user clicks the button, the VBA will unhide the sheet and refresh the query.
I have a table on Sheet1. I want to pull in data into this table based on entry in another tab.
For example, I have a table
based on information in other tabs, I want to populate the Score column.
Can this be accomplished using SQL query or Powerquery (pseudocode- Select "Score" from other tab where Name = Jack )
I can look for events in VBA when if data is entered in the other tabs it can grab it and paste it in this table but it seems messy.
The reason I want to do this is, there are multiple tabs where people can enter their Scores. They cannot enter this in the main tab otherwise I wouldn't have a problem.
Load all datasets from your worksheet to PowerQuery and keep them as connections only (w/o loading to worksheet) except the one that you want to populate with the data in the end. After loading you can merge different datasets using selected columns as the key for joining. The result of the merge would be a table from which you could retrieve particular columns of interest.
The Excel file I receive is very "irregular" ... the first few rows are just descriptions and random information.
I want to start reading the file from row #17 and ONLY visible rows.
Row 17 is the header for the columns (like a normal table).
Is such a thing even possible?
In the excel connection you can set openRowset, selecting cells from your sheet like Excel,
Example: openRowset: Sheet1$A17:f30
Check this link add the script counter to your package then you can do a conditional split task for MyCounter > 17, if you do this straight after the import it should contain the correct rows.
I'm not sure what you mean by visible rows though. If you get rows that are fully Null then you can always add that to the condition.
The excel file can be queried like sql statement. In your data flow task, take excel source set the conncetion manager as excel then data access mode as sql command. write the query on excel.
Example
Consider your worksheet name as Sheet1, having columns ID, Name, Dept and your data starts from 17 write the query like this
SELECT [ID],[Name],[Dept] from [Sheet1$A17:C65536] Where [ID] is not null.
This query selects data from row 17 to end of the excel until where data exists.
If your header row is A17 dont forget to check "first row has column names" in connection manager.
I have created 2 variable one for File Name and other for Sheet Name and store the values from “for each loop” container to it.
I have made an Excel Connection manager and then take the sheet Name from variable which I have created in variable:
Now I have select Data Access mode as “SQL command from variable”.And then Select variable Name from drop down.
I have to read data from query_2 which I have created in Variable and in which i have used sheet name as variable "SELECT * FROM "+"["+REPLACE(#[User::FileName],".XLSX","$A35:R]")` to Select the range of data which is available in sheet .
Click here for a clear explanation with example