Moving one column to the end of another - excel

I have a bunch of excel files that are formatted in a pretty weird way that I would like to make an automated import script for, so I can easily get this data into a sheet with the correct formatting.
It has hourly values for each month in the first 12 columns, then the date along with hours in the next 12 columns.
What I would like to do is be able to get this data in to a table where the first column has the date and hour (in excel format) and the second one containing the data. My thought was to record a macro during the process of adjusting the data with power query and then repeating the macro with multiple files. However, I can't seem to find a good way to make "Column 2"'s data moved to the end of "Column 1" and repeating that for both values and the dates using Power Query. Any pointers?
Also notice, column 1s length differs from column 2 since January has more values than February. However, column 1s lenght is the same as column 13, column 2s length same as 14 and so on.
I have uploaded a sample file here

Create a blank query from scratch (on my machine I do this in Excel via: Data > Get Data > From Other Sources > Blank Query).
Click Home > Advanced Editor, copy-paste the code below and change this line folderPath = "C:\Users\user\", to the path of the parent folder that contains the Excel files. Then click Close & Load.
As the data is being imported from multiple workbooks (and possibly multiple sheets), the first two columns of the loaded table should be the workbook and worksheet that that row of data came from. (If you want to get rid of the first two columns, edit the query.)
let
folderPath = "C:\Users\user\",
getDataFromSheet = (sheetData as table) =>
let
promoteHeaders = Table.PromoteHeaders(sheetData, [PromoteAllScalars=true]),
standardiseHeaders =
let
headers = Table.ColumnNames(promoteHeaders),
zipWithLowercase = List.Zip({headers, List.Transform(headers, Text.Lower)}),
renameAsLowercase = Table.RenameColumns(promoteHeaders, zipWithLowercase)
in
renameAsLowercase,
emptyTable = Table.FromColumns({{},{}}, {"Date", "Value"}),
monthsToLoopOver = {"januari", "februari", "mars", "april", "maj", "juni", "juli", "augusti", "september", "oktober", "november", "december"},
appendEachMonth = List.Accumulate(monthsToLoopOver, emptyTable, (tableState, currentMonth) =>
let
selectColumns = Table.SelectColumns(standardiseHeaders, {currentMonth & "tim", currentMonth}, MissingField.UseNull),
renameColumns = Table.RenameColumns(selectColumns, {{currentMonth & "tim", "Date"}, {currentMonth, "Value"}}),
appendToTable = Table.Combine({tableState, renameColumns})
in
appendToTable
),
tableOrNull = if List.Contains(Table.ColumnNames(standardiseHeaders), "januari") then appendEachMonth else null
in
tableOrNull,
getDataFromWorkbook = (filePath as text) =>
let
workbookContents = Excel.Workbook(File.Contents(filePath)),
sheetsOnly = Table.SelectRows(workbookContents, each [Kind] = "Sheet"),
invokeFunction = Table.AddColumn(sheetsOnly, "f", each getDataFromSheet([Data]), type table),
appendAndExpand =
let
selectColumnsAndRows = Table.SelectColumns(Table.SelectRows(invokeFunction, each not ([f] is null)), {"Name", "f"}),
renameColumns = Table.RenameColumns(selectColumnsAndRows, {{"Name", "Sheet"}}),
expandColumn = Table.ExpandTableColumn(renameColumns, "f", {"Date", "Value"})
in
expandColumn
in
appendAndExpand,
filesInFolder = Folder.Files(folderPath),
validFilesOnly = Table.SelectRows(filesInFolder, each [Extension] = ".xlsx"),
invokeFunction = Table.AddColumn(validFilesOnly, "f", each getDataFromWorkbook([Folder Path] & [Name])),
appendAndExpand =
let
selectRowsAndColumns = Table.SelectColumns(Table.SelectRows(invokeFunction, each not ([f] is null)), {"Name", "f"}),
renameColumns = Table.RenameColumns(selectRowsAndColumns, {{"Name", "Workbook"}}),
expandColumn = Table.ExpandTableColumn(renameColumns, "f", {"Sheet", "Date", "Value"})
in
expandColumn,
excludeBlankDates = Table.SelectRows(appendAndExpand, each not (Text.StartsWith([Date], " "))),
transformTypes =
let
dateAndHour = Table.TransformColumns(excludeBlankDates, {{"Date", each Text.Split(_, " ")}}),
changeTypes = Table.TransformColumns(dateAndHour, {{"Workbook", Text.From, type text}, {"Sheet", Text.From, type text}, {"Date", each DateTime.From(_{0}) + #duration(0, Number.From(_{1}), 0, 0), type datetime}, {"Value", Number.From, type number}})
in
changeTypes
in
transformTypes
For reliability and robustness, it would be good if you create a folder and put all Excel files (that need restructuring) into that folder -- and ensure nothing else goes into that folder (not even the file that will be doing the importing/restructuring).
If you can't do this for whatever reason, then click the validFilesOnly step whilst in the Query Editor and amend the filter criteria, such that the table only includes files you want restructured.

You can do the formatting pretty quickly by writing your own macro in VBA. Then you can create another macro to run the formatting macro on multiple files within a folder.
Run same excel macro on multiple excel files
Here is an example of a macro that will reformat your data closer to what you are looking for.
Sub FormatBlad()
' create a new sheet and rename it
Sheets.Add After:=ActiveSheet
Sheets(Sheets.Count).Name = "Formatted"
' set helper variables
Dim blad As Worksheet
Dim format As Worksheet
Set blad = Sheets("Blad1")
Set ft = Sheets("Formatted")
Dim blad_row_num As Integer
Dim ft_row_num As Integer
Dim month_offset As Integer
blad_row_num = 2
ft_row_num = 2
month_offset = 13 ' column N - 1
' set column headers in formatted sheet
ft.Range("A1").Value = "Date"
ft.Range("B1").Value = "Value"
' loop through months
For i = 1 To 12
blad_row_num = 2
While blad.Cells(blad_row_num, i).Value <> ""
ft.Cells(ft_row_num, 1).Value = blad.Cells(blad_row_num, month_offset + i).Value
ft.Cells(ft_row_num, 2).Value = blad.Cells(blad_row_num, i).Value
blad_row_num = blad_row_num + 1
ft_row_num = ft_row_num + 1
Wend
Next i
End Sub

Related

Excel Power Query to only show unhidden rows

i have an excel workbook with 3 worksheets. each of the worksheet contains hidden and unhidden rows. i’ve managed to combine all 3 worksheets into one single worksheet via power query. however, the worksheet generated shows all the hidden and unhidden rows. is there anyways i could just generate the worksheet with just the unhidden rows?
i’ve read about using a helping column and applying a filter on it but i am unsure of how to do that as well. any new suggestions/walkthrough is greatly appreciated
You can do this in Power Query.
You can unzip the XLSX file to XML tables, and examine the row attributes - then get the sheet data, and merge the hidden attribute with the row number.
Pass this function the file name (including path) and sheet name, and it will return the sheet contents, with an added "Row hidden" column:
//fnGetRowHiddenStatus
(MyFileName as text, MySheetName as text) =>
let
fnUnzip = (ZIPFile, Position, FileToExtract, DataSoFar) =>
let
MyBinaryFormat = try BinaryFormat.Record([DataToSkip=BinaryFormat.Binary(Position),
MiscHeader=BinaryFormat.Binary(18),
FileSize=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian),
UnCompressedFileSize=BinaryFormat.Binary(4),
FileNameLen=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian),
ExtrasLen=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian),
TheRest=BinaryFormat.Binary()]) otherwise null,
MyCompressedFileSize = try MyBinaryFormat(ZIPFile)[FileSize]+1 otherwise null,
MyFileNameLen = try MyBinaryFormat(ZIPFile)[FileNameLen] otherwise null,
MyExtrasLen = try MyBinaryFormat(ZIPFile)[ExtrasLen] otherwise null,
MyBinaryFormat2 = try BinaryFormat.Record([DataToSkip=BinaryFormat.Binary(Position), Header=BinaryFormat.Binary(30), Filename=BinaryFormat.Text(MyFileNameLen), Extras=BinaryFormat.Binary(MyExtrasLen), Data=BinaryFormat.Binary(MyCompressedFileSize), TheRest=BinaryFormat.Binary()]) otherwise null,
MyFileName = try MyBinaryFormat2(ZIPFile)[Filename] otherwise null,
GetDataToDecompress = try MyBinaryFormat2(ZIPFile)[Data] otherwise null,
DecompressData = try Binary.Decompress(GetDataToDecompress, Compression.Deflate) otherwise null,
NewPosition = try Position + 30 + MyFileNameLen + MyExtrasLen + MyCompressedFileSize - 1 otherwise null,
AsATable = Table.FromRecords({[Filename = MyFileName, Content=DecompressData]}),
#"Appended Query" = if DecompressData = null then DataSoFar else if (MyFileName = FileToExtract) then AsATable else
if (FileToExtract = "") and Position <> 0 then Table.Combine({DataSoFar, AsATable})
else AsATable
in
if (MyFileName = FileToExtract) or (#"Appended Query" = DataSoFar) then
#"Appended Query"
else
#fnUnzip(ZIPFile, NewPosition, FileToExtract, #"Appended Query"),
Unzipped = fnUnzip(File.Contents(MyFileName), 0, "", null),
WorkbookXML = Xml.Tables(Table.SelectRows(Unzipped, each Text.Contains([Filename],"xl/workbook"))[Content]{0}),
WorkbookData = Table.SelectRows(WorkbookXML, each [Name] = "sheets"){0}[Table]{0}[Table],
SheetIDs = Table.ExpandTableColumn(WorkbookData, "http://schemas.openxmlformats.org/officeDocument/2006/relationships", {"Attribute:id"}, {"Attribute:id"}),
SheetID = Text.Replace(Table.SelectRows(SheetIDs, each ([#"Attribute:name"] = MySheetName))[#"Attribute:id"]{0},"rId","sheet"),
SheetXML = Xml.Tables(Table.SelectRows(Unzipped, each Text.Contains([Filename], "worksheets/" & SheetID))[Content]{0}),
SheetData = Table.SelectRows(SheetXML, each [Name]="sheetData"){0}[Table]{0}[Table],
Renamed = Table.RenameColumns(SheetData,{{"Attribute:r", "Row"}}),
#"Row Data" = Table.SelectColumns(Renamed,{"Row", "Attribute:hidden"}, MissingField.Ignore),
#"Changed Type" = Table.TransformColumnTypes(#"Row Data",{{"Row", Int64.Type}}),
#"Row Status" = Table.AddColumn(#"Changed Type", "Hidden", each try if [#"Attribute:hidden"] = "1" then true else false otherwise false, type logical),
Workbook = Excel.Workbook(File.Contents(MyFileName)),
Worksheet = Table.SelectRows(Workbook, each ([Name] = MySheetName))[Data]{0},
#"Added Row" = Table.AddIndexColumn(Worksheet, "Row", 1, 1, Int64.Type),
#"Merged Row Status" = Table.NestedJoin(#"Added Row", {"Row"}, #"Row Status", {"Row"}, "Row Status", JoinKind.LeftOuter),
#"Expanded Row Status" = Table.ExpandTableColumn(#"Merged Row Status", "Row Status", {"Hidden"}, {"Row hidden"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Row Status",{"Row"})
in
#"Removed Columns"
Example:
let
Source = fnGetRowHiddenStatus("C:\Temp\rowhide.xlsx", "Sheet1")
in
Source

update data via macro from another workbook

I need some help with vba code. I'm self-lerning so please be understanding for simply cases ;)
I'm trying to create macro which will be looking for some records/cells in one workbook (FileA) (determined by 3 conditions) and then paste values to another workbook (FileB) and after that find in another tab in FileB some values where condition will be pasted value to match them with looking value (I belivie it could be done somehow with Vlookup but I get stuck).
Below problematic for me part of code (I'm working on some files found in work, no one use it now).
First issue is with Set Update, I don't know why it takes it as "Nothing"... conditions are true - I mean "pp1" is existing in column A in FileA.
Second issue shows when I change i start range to some "later" numbers, eg From i = 2280, macro is ignoring last line where should assign some values (again shows update2 as "nothing") but value if pp2 is existing in W column in tab data...
Dim name As String
name = "[path to file on sharepoint]"
Application.ScreenUpdating = False
Workbooks.Open Filename:=name
a = 1
For i = 2263 To 14000
If Workbooks("FileA").Sheets("Main").Cells(i, 11) = "CANCEL" And Workbooks("FileA").Sheets("Main").Cells(i, 6) = "DENIS" And Workbooks("FileA").Sheets("Main").Cells(i, 5) > 1301358454 Then
pp1 = Workbooks("FileA").Sheets("Main").Cells(i, 1)
If pp1 > 0 Then
Set Update = Workbooks("FileA").Worksheets("Main").Range("A:A").Find(pp1, lookat:=xlPart)
If Update > 0 Then
Update = Update.Row
Workbooks("FileB").Worksheets("lost").Cells(a, 1).Value = Workbooks("FileA").Worksheets("Main").Cells(Update, 5)
pp2 = Workbooks("FileB").Worksheets("lost").Cells(a, 1)
update2 = Workbooks("FileB").Worksheets("data").Range("W:W").Find(pp2, lookat:=xlPart).Row
Workbooks("FileB").Worksheets("lost").Cells(a, 5) = Workbooks("FileB").Worksheets("data").Cells(update2, 43)

Location causes incorrect placement of separators in Excel during file import

I import large amounts of data into Excel. These are previously reduced in quantity from 100 Hz to 1 Hz by a third-party program to reduce work and load time. However, during this reduction process, decimal and thousands separators are swapped, probably because the software is designed in a different language.
Original (Example line):
009 090308.510 +2475.77145123 -0091.51682637 070.530 271.89 +0168.67 +0001.13 -8.485680E-04 0.000000 +4.625850E-04 +2.679440E+36 -2.544081E-29 +2.658468E+36
Processed by third party program:
009 090308,510 +2475,77145123 -0091,51682637 070,530 271.89 +00168,67 +001,130 0,000000 -8.485680E-04 +4.625850E-04 +2.679440E+36 -2.544081E-29 +2.658468E+36
As can be seen, some separators are swapped by the program, but others are not. If I now apply my import code to both formats, I get the following results:
Original:
9 90308.51 2475.771 -91.5168 70.53 271.89 168.67 1.13 -8.49E-04 0 4.63E-04 2.68E+36 -2.54E-29 2.66E+36
Processed:
9 90,308,510 247,577,145,123 -9,151,682,637 40,530 271.89 +00168,67 1,130 0,000000 -8.49E-04 4.63E-04 2.68E+36 -2.54E-29 2.66E+36
For understanding here the code for import:
Option Explicit
Public Sub fileImporter()
Dim fDialog As FileDialog
Dim fPath As Variant
Dim FSO
Dim Data
Dim arr, tmp, output
Dim file, fileName As String
Dim x, y As Integer
Dim newSht As Worksheet
Application.ScreenUpdating = False
Set fDialog = Application.FileDialog(msoFileDialogFilePicker)
With fDialog
.AllowMultiSelect = True
.Title = "Please select files to import"
.Filters.Clear
.Filters.Add "VBO Files", "*.vbo" 'VBO Files are opened and handled like Text Files
If .Show = True Then
For Each fPath In .SelectedItems
Set FSO = CreateObject("Scripting.FilesystemObject")
fileName = FSO.GetFilename(fPath)
Set Data = FSO.OpentextFile(fPath)
file = Data.readall
Data.Close
arr = Split(file, vbCrLf)
ReDim output(UBound(arr), 50)
For x = 0 To UBound(arr)
tmp = Split(arr(x), " ")
For y = 0 To UBound(tmp)
output(x, y) = tmp(y)
Next
Next
Set newSht = ActiveWorkbook.Sheets.Add(after:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
newSht.Name = fileName
Sheets(fileName).Range("A1").Resize(UBound(output) + 1, UBound(output, 2)) = output
Next
End If
End With
Application.ScreenUpdating = True
End Sub
The record of the processed file is not separated rudimentarily correctly and reasonably. I have also already tried using
With Application
.DecimalSeparator = "."
.ThousandsSeparator = ","
.UseSystemSeparator = False
End With
but that did not work either. Or rather, it changed the separators, but the result stayed the same. The numbers were not separated at the correct places.
I found a similar question here (Importing CSV US formatted numbers in Excel with localisation), which seems to be the same problem. But since the import function in the answer is different from mine, I am not sure how to integrate it properly.
Does someone have a idea? Maybe a way how to preserve the format while or during splitting? Or a better place to integrate the Application.DecimalSeparator argument in the given code?
Thanks for the help!
EDIT:
The problem could be solved by comparing system settings. Apparently, the computer was not provided with the default settings by IT and some settings of the previous owner were still present. These included a partial language change to German, as well as a permanent replacement of the decimal and thousands separators in Excel, instead of using the system separators. After correcting these settings, the program and import works without incorrect separator usage.
You may be able to obtain your desired output using Power Query, available in Windows Excel 2010+ and Office 365 Excel
Data => Get &Transform => From Text/Csv
When the initial dialog opens, ensure Space is selected as the Delimiter
Select Transform Data
Select Home=>Advanced Editor
Replace the code after your Source line with the code below (after Source)
Edit change in swapping algorithm
It appears by examination that
All columns are numeric
Separators are swapped on the columns where there is a comma
All other columns have the separators not swapped
If those assumptions are not correct, some changes may need to occur
If there are swapped and non-swapped values in a single column, I would suggest you develop another method to sample your data, else you would have to check every single cell
M Code edited to implement change in algorithm above
M Code edited to check first 200 table rows for commas instead of just first row
let
Source = Csv.Document(File.Contents("C:\Users\ron\Desktop\decimals.txt"),
[Delimiter=" ", Columns=14, Encoding=1252, QuoteStyle=QuoteStyle.None]),
//Swapped separators = numbers with commas
// check only the first 200 rows, for efficiency
#"Check Table" = Table.Buffer(Table.FirstN(Source, List.Max({Table.RowCount(Source), 200}))),
Swapped = List.Accumulate(Table.ColumnNames(#"Check Table"), {}, (state, current)=>
if List.AnyTrue(List.Transform(Table.Column(#"Check Table", current), each Text.Contains(_,",")))
then state & {current} else state),
notSwapped = List.RemoveMatchingItems(Table.ColumnNames(#"Check Table"),Swapped),
//Set the data types appropriately
#"Type Not Swapped"= Table.TransformColumnTypes(Source,
List.Transform(notSwapped, each {_, type number}),"en-US"),
#"Type Swapped" = Table.TransformColumnTypes(#"Type Not Swapped",
List.Transform(Swapped, each {_, type number}),"da-DK")
in
#"Type Swapped"
Original Data
| 009 | 090308,510 | +2475,77145123 | -0091,51682637 | 070,530 | 271.89 | +00168,67 | +001,130 | 0,000000 | -8.485680E-04 | +4.625850E-04 | +2.679440E+36 | -2.544081E-29 | +2.658468E+36 |
Results

Power Query - Get Data from AnalysisServices (Cube) - Filter with User-Function result

I have the following problem. I'm getting Data (Excel 365 - Power Query) from a Cube with "Get Data from Analysis Services". -> Selling Qty an Values for filtered years by week.
Every thing is fine if I use Filter, updatetime ca. 3-4 seconds:
#"Filtered Rows1" = Table.SelectRows(#"Added Items", each
(Cube.AttributeMemberId([#"Date.Year (4-4-5)"]) = "[Date].[Year 4-4-5].&["&
Number.ToText(2019) &"]" meta
[DisplayName = Number.ToText(2019)]
or Cube.AttributeMemberId([#"Date.Year (4-4-5)"]) = "[Date].[Year 4-4-5].&["&
Number.ToText(2020) &"]" meta
[DisplayName = Number.ToText(2020)]
)
Now I like to do that dynamic, so that I can get the years from a cell in excel. I use the following M-Function "fktGetNamedCellValue" for this:
let
Source = (FieldInput as text) =>
let Quelle = Excel.CurrentWorkbook(){[Name=FieldInput]}[Content],
Inhalt = Number.From(Quelle{0}[Column1])
in Inhalt
in Source
I replaced the years in the Filter-Step with the function.
The cells are named "cell_Prev_Year" and "cell_Plan_Year"
The cells in Excel formated as Numbers (and there are only Numbers in it)
The updatetime now -> endless!!!
#"Filtered Rows1" = Table.SelectRows(#"Added Items", each
(Cube.AttributeMemberId([#"Date.Year (4-4-5)"]) = "[Date].[Year 4-4-5].&["&
Number.ToText(fktGetNamedCellValue("cell_Prev_Year") &"]" meta
[DisplayName = Number.ToText(fktGetNamedCellValue("cell_Prev_Year"))]
or Cube.AttributeMemberId([#"Date.Year (4-4-5)"]) = "[Date].[Year 4-4-5].&["&
Number.ToText(fktGetNamedCellValue("cell_Plan_Year")) &"]" meta
[DisplayName = Number.ToText(fktGetNamedCellValue("cell_Plan_Year"))]
)
If I use a "normal" parameter with the value "2019" or "2020" everything is fine.
Only if I use the fktGetNamedCellValue it will not run correctly.
I`ed Trim an Clean the result. Formated it as Text and Number... nothing helped.
I have to use userfriendly Parameter (not set in Power Query) for this, so I hope for some help :)
Best Regards
Chris
(PS: I hope u understand my english)
I solved this problem as follows.
Since it is not an good idea to use an user-function as parameter to get data from an cube. I think this method disables query-folding or is called a lot of times in the process, I decided to use an power-query parameter.
I change this Parameter with vba by checking the worksheet_change event and calling this sub:
Sub refresh_Parameter(ParameterName As String, ParameterValue As Variant)
Dim strOldFormula As String
Dim strParametersMeta As String
strOldFormula = ThisWorkbook.Queries(ParameterName).Formula
strParametersMeta = Mid(strOldFormula, InStr(1, strOldFormula, "meta"), Len(strOldFormula))
ThisWorkbook.Queries(ParameterName).Formula = ParameterValue & " " & strParametersMeta
Debug.Print strOldFormula
Debug.Print strParametersMeta
End Sub
The parameters for the sub arte the PARAMETER Name in PowerQuery and the VALUE which should be set. For this the sub extracts the meta-data from the query-formula and combines it with the new Value.
Maybe someone needs this :)
Best regards chris

Replace SQL query parameter in a Excel power query

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.
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.
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

Resources