Get Current Workbook Path - Excel Power Query - excel

Trying to add a custom column and populating the value with the current workbook path name.
I have tried Excel.Workbook.name and Excel.CurrentWorkbook() and other objects, but it seems those are limited to pulling data.
in VBA this is simply WorkbookObject Path property. but with power query its another story. The references and libraries on Microsoft site are limited for power query.
https://msdn.microsoft.com/en-us/library/mt779182.aspx

Instead of using VBA, you can use the following method which merely involves using an Excel formula:
Define the following formula in Excel and name this cell "FilePath":
=LEFT(CELL("filename",$A$1),FIND("[",CELL("filename",$A$1),1)-1)
Add the following function in PowerQuery. This will return the current directory:
() =>
let
CurrentDir = Excel.CurrentWorkbook(){[Name="FilePath"]}[Content]{0}[Column1]
in
CurrentDir
Now you can import your CSV (or other) file from the current directory:
let
Source = Csv.Document(File.Contents(currentdir() & "filename.csv"),[Delimiter=";", Columns=15, Encoding=65001, QuoteStyle=QuoteStyle.None])
in
Source
Credits: https://techcommunity.microsoft.com/t5/excel/power-query-source-from-relative-paths/m-p/206150

There is no direct way to do this in Power Query. If you can fill the value into a cell you can get that value through Excel.CurrentWorkbook.

You can use VBA and have a cell filled in when the file is opened during the Workbook_Open event:
Private Sub Workbook_Open()
Dim root As String
root = ActiveWorkbook.path
Range("root").Value = root
'root is the named range used in power query.
End Sub
You can then get this variable from the named range ("root") into Power Query by doing something along these lines:
let
Source = Excel.CurrentWorkbook(){[Name="root"]}[Content][Column1]{0}
in
Source

Related

Relative folder/file path in PowerQuery (M)

Given: 2 excel files (A and B) that are located in the same folder.
Task: set Source for a given PQ in Workbook B to reference Workbook A in a "relative" manner - when both files are moved to another PC the reference isn't broken.
Is there anything in M-language to get current folder or file path?
You need to give a name 'Path' to some cell where current path is defined
=LEFT(CELL("filename");SEARCH("[";CELL("filename");1)-1)
Then use following in the query:
Path = Excel.CurrentWorkbook(){[Name="Path"]}[Content]{0}[Column1],
FullPath = Path & "file.xlsx",
Source = Excel.Workbook(File.Contents(FullPath), null, true)
One big disadvantage of the approach - is that you need to Calculate your workbook after localtion is changed or set Calculation mode to Automatic.
If someone know how can we do not use cell for getting current path - it will solve a problem with modifying file and Calculation mode.
Give an excel cell a range name, like LocVariable, and put some text or excel formula in that cell to evaluate to the filepath you want, such as c:\temp
Then in powerquery, in home ... advanced editor ... edit your Source statement to use that path
let Loc = Text.From(Excel.CurrentWorkbook(){[Name="LocVariable"]}[Content]{0}[Column1]),
Source = Excel.Workbook(File.Contents(Loc&"\data.xlsx"), null, true),
or in one step
let Source = Excel.Workbook(File.Contents(Text.From(Excel.CurrentWorkbook(){[Name="LocVariable"]}[Content]{0}[Column1])&"\data.xlsx"), null, true),

Excel Multiple data connections to same table

I have a worksheet DATA with the table populated from json file through the Microsoft Query.
There're different json files so I need to create several connections to any of those files.
I also have a cell on another worksheet where I would like to indicate a parameter (for example Yesterday,Today,Tomorrow).
According to selected parameter the table in the DATA worksheet should be populated from the related data connection (yesterday.json, today.json, tomorrow.json).
Is it possible to do it? If yes, what would be the procedure?
I have an idea that it might be possible to do by changing the filename inside the query.
For example, this is my query:
let
FilePath = Excel.CurrentWorkbook(){[Name="FilePath"]}[Content]{0}[Column1],
FullPathToFile1 = FilePath & "\json\today.json",
Source = Json.Document(File.Contents(FullPathToFile1)),
So am thinking if there's some way to "inject" filename in the above query based on value of some cell.
Will appreciate any help, links etc.
Thanks!
UPDATE:
I have created a named cell jsonPath and put the file name in it.
Then I have modified above query as follows, but it gives me an error.
FilePath = Excel.CurrentWorkbook(){[Name="FilePath"]}[Content]{0}[Column1],
FullPathToFile1 = FilePath & "\json\" & [jsonPath],
Source = Json.Document(File.Contents(FullPathToFile1)),
I got it working by modifying my query as follows:
FilePath = Excel.CurrentWorkbook(){[Name="FilePath"]}[Content]{0}[Column1],
FileName = Excel.CurrentWorkbook(){[Name="jsonPath"]}[Content]{0}[Column1],
FullPathToFile1 = FilePath & "\json\" & FileName,
Source = Json.Document(File.Contents(FullPathToFile1)),

Create Revit Sheets from Excel with multiple project parameters

Hi I have a macro that creates multiple sheets and has Name, Number, Sheet Category. The last being my own project parameter.
I can successfully create the sheets with name and number but I am having difficulty adding the value from CSV file to the project parameter "SD_Sheet Category". Below are some code grabs to help explain.
Public Module mSheetCreator
Public Structure structSheet
Public sheetNum As String
Public sheetName As String
Public sortCategory As String
End Structure
Then I have a function that reads the CSV file and does the following:
Try
currentRow = MyReader.ReadFields()
'create temp sheet
Dim curSheet As New structSheet
curSheet.sheetNum = currentRow(0)
cursheet.sheetName = currentRow(1)
curSheet.sortCategory = currentRow(4)
'add sheet to list
sheetList.Add(curSheet)
Then I have a transaction that does the following:
For Each curSheet As structSheet In sheetList
Try
If sheetType = "Placeholder Sheet" Then
m_vs = ViewSheet.CreatePlaceholder(curDoc)
Else
m_vs = ViewSheet.Create(curDoc, tblock.Id)
m_vs.Parameter("SD_Sheet Category").Set(CStr(curSheet.sortCategory))
End If
m_vs.Name = curSheet.sheetName
m_vs.SheetNumber = curSheet.sheetNum
The problem is this code:
m_vs.Parameter("SD_Sheet Category").Set(CStr(curSheet.sortCategory))
I am getting a warning that says it's an "implicit conversion from 'String' to 'Autodesk.Revit.DB.BuiltInParameter'"
once I build solution
When I run the code in Revit it produces an error saying
"Conversion from string 'SD_Sheet Category" to type 'Integer' is not valid"
It creates the sheets but disregards all the info in the CSV file. I know the rest of the code works as I have removed this particular line of code so I know it isn't the problem
Any suggestions??
I believe that as of a particular version of Revit API you cannot use .Parameter(“name”)
Because there might be two parameters with the same name.
So you need to do something more like
Dim cat as Parameter
Cat = m_vs.GetParameters(“sd_sheet category”).First()
Cat.Set(CSTR(cursht.sortCategory))
Good luck!

Extracting the Company property from a Word document using Excel VBA

I'm using Excel 2010 and VBA to reorganize some Word documents on my C:\ drive and I want to pull the "Company" property of each document into a sheet containing a list of documents. The full file path of each document appears in row A (like so: "C:\folder\subfolder\file.doc"),and I would like to populate the corresponding "Company" property in row F.
I'm trying to write a macro for a custom Excel function DocCompany that will use a text string containing a local filepath to return the "Company" property of the document that the filepath identifies.
I've had better luck with the Last Modified and File Size properties, as both have dedicated VBA functions (FILEDATETIME and FILELEN, respectively). In each case, all I had to do was write a macro for a custom Excel function that returns the result of the VBA function for a file path string located in the sheet.
Given the following function, =GetFileDateTime(A1) will return the last save date for the document identified by the filepath string contained in A1.
Function GetFileDateTime(FileName As String) As Date
GetFileDateTime = FileDateTime(FileName)
End Function
Given the following function, =FileSize(A1) will return the file size in bytes of the document identified by the filepath string contained in A1.
Function FileSize(FileName As String)
FileSize = FileLen(FileName)
End Function
However, the Company property has no corresponding VBA function, so (as I said above), I want to write a macro defining a custom Excel function DocCompany that will accept a local filepath string as input and use it to output the Company property of the document.
This is what my macro looks like right now:
Function CompanyID(FileName As String) As String
CompanyID = Documents(FileName).Open
Documents(FileName).BuiltinDocumentProperties (wdPropertyCompany)
End Function
When I try to save it, Excel returns the error message "Compile error: Sub or Function not defined". Then it selects the reference to the "Documents" collection in the second row.
Why does Excel insist that I define "Documents" as a variable when every reference I can find confirms that it IS in fact an object or collection? What can I do to make this code work? Do I need to take a different approach?
Why does Excel insist that I define "Documents" as a variable when every reference I can find confirms that it IS in fact an object or collection?
Since Documents is not part of the Excel object model, it is being interpreted as a variable. You need to bind Word to the Excel instance, and reference that instance of the Word Application class.
Function CompanyID(FileName As String) As String
Dim wdApp as Object 'WOrd.Application
Dim doc as Object 'Word.Document
Const wdPropertyCompany as Long = 21 'Explicit reference for late-bound Word Application
Set wdApp = CreateObject("Word.Application")
Set doc = wdApp.Documents.Open(FileName)
CompanyID = doc.BuiltinDocumentProperties (wdPropertyCompany)
doc.Close False
End Function
Function F_snb(c00)
With GetObject(c00)
F_snb = .BuiltinDocumentProperties(21)
.Close 0
End With
End Function
in A2: G:\OF\example.docx
in D2: =F_snb(A2)

importing data from many workbooks in different folders

I am looking to import/copy data from many workbooks into a summary workbook. The workbooks are arranged in different sub-folders, I.e
C:\data1\results_2001.xlm
C:\data2\results_2002.xlm
C:\data3\results_2003.xlm
The names are similar but differ slightly to differentiate them. At present, I import the files individually, and I want to automate the process. The results files (above) are amongst other excel files so I cannot target them by file type.
How would I import these files by partial file name?
One option is to create an array of the filepaths to your excel sheets and then loop over the array and get the data you want into your summary sheet.
Sub CreateSummary()
Dim wkbs() As Variant, wkb As Integer, owb As Workbook
wkbs = Array("C:\data1\results_2001.xlm", "C:\data2\results_2002.xlm", "C:\data3\results_2003.xlm")
For wkb = 0 To UBound(wkbs)
Set owb = Application.Workbooks.Open(wkbs(wkb)) //Open each workbook
With owb
//Get the data you want into your summary workbook
.Close
End With
Next wkb
End Sub
Another way, especially if only a one time operation: Go into Cmd.exe, do a Dir for the files you're looking for, and send it to a text file (eg, something like dir c:\results_*.xlm /s /b > c:\myList.txt). Then import the text file to your worksheet, step thru each cell in the list, opening each workbook in turn.
You can do it in any languages, but for you who is asking this question, i think it's gonna be a little challenging, so here is what you need to do :
create a function that will list files/folders from given path
loop through all items found, if it's a folder , recursive it
if the item fits your target(name, extension, ...) , read it and load the content to the summary
something like this, i believe you will achieve this easily using VBA, look here
Literally, it will be like this, please note that this is not valid code, just something i write down to help you figure it out :
function loopthepath (string pathtoloop)
foreach(dirItem item in pathtoloop.getdirItem)
{
if (item is folder)
{
loopthepath(pathtoloop + item)
}
else
{
if (item fits mydescription)
{
load the content to the summary
}
}
}

Resources