Import Global Address Book from Outlook to Excel or Power BI - Power Query - excel

Has anyone experience how to import global address book from Outlook to Excel/Power BI using Power Query?
I managed to retrieve some of users from my Companies Email using Data from > Exchange Online
let
Source = Exchange.Contents("XYZ.com"),
People = Source{[Name="People"]}[Data]
in
People
But it doesnt give me whole list of Outlook users from the Company...
I found different code but doesnt work for me, it says: my domain doesnt exist. And I am not very familiar with Active Directory and so on...any inputs and tricks?
let
Source = ActiveDirectory.Domains("CompanyDomain.com"),
CompanyDomain.com = Source{[Domain = "CompanyDomain.com"]}[Object Categories],
user = CompanyDomain.com{[Category = "user"]}[Objects],
#"Removed Other Columns" = Table.SelectColumns(user, {"displayName", "user",
"organizationalPerson"}),
#"Expanded organizationalPerson" = Table.ExpandRecordColumn(#"Removed Other Columns",
"organizationalPerson", {"department"}, {"department"}),
#"Expanded user 1" = Table.ExpandRecordColumn(#"Expanded organizationalPerson", "user",
{"mail"}, {"mail"})
in
#"Expanded user 1"
I am using Office365 version.

Create a query that is just the source line above. For example:
let
Source = ActiveDirectory.Domains("yourdomain.com")
in
Source
In Power Query, when you click on the Source line on the right, what does it show? In my case, I get a table of domains. It would be one of those values you would use in the "CompanyDomain.com =" line above.
If Source is giving you the error about not finding the domain, then you'll have to have someone tell you what that value is for your company. (Mine was automatically filled in when I chose the Active Directory connector, and it's not just CompanyName.com.)
Hope it helps,
Alan

Related

Getting "Please rebuild this data combination" on a computer but not on another one

This is my first try at using the Power Query... I've build a "dynamic" query in which I can change the retrieved fields as well as the filtering fields and values to be used by the query.
It's working perfectly on my computer but as soon as I try to execute it on another computer, I get the "Please rebuild this data combination" error. I saw some post saying I'll have to kind of split my query but I have not been able to figure it out.
Here is what my 2 tables look like:
Condition and fields selection
and here is my Query with the error:
Query
This might not be very elegant, but it allow me, thru a VBA script, to generate the list of fields to be retrieved and to generate the condition to be used by the SQL.
Any idea why it's not working on the other computers or how to improved the solution I'm using?
Thank you!
Notes:
Hi, all my Privacy Level are already set to 'None'.
I've tried to parametrize my code but I can't figure how. The Where condition is dynamic: it could be Where Number = "1234" but in other condition, the where might be like: 'Where Assignee = "xyz"'.
Here is a simplified example of my code:
let
Source = Sql.Database("xxxx", "yyyy", [Query=
"Select network, testid
from CM3T1M1 "
& paramConditions[Conditions]{0} &
" "])
in
Source
rebuild query, Formula.Firewall
That's a feature to prevent prevent accidentally leaking data. You can change the privacy level to ignore it
See also: docs.microsoft/dataprivacyfirewall
Is the dynamic query inserting those cells into the SQL query ? Report Parameters are nice for letting the user change variables without having to re-edit the query.
Parameterized native SQL queries
from: https://blog.crossjoin.co.uk/2016/12/11/passing-parameters-to-sql-queries-with-value-nativequery-in-power-query-and-power-bi/
let
Source = Sql.Database("localhost", "Adventure Works DW"),
Test = Value.NativeQuery(
Source,
"SELECT * FROM DimDate
WHERE EnglishMonthName=#MonthName AND
EnglishDayNameOfWeek=#DayName",
[
MonthName = "March",
DayName = "Tuesday"
]
)
in
Test
Dynamic Power Query version of SQL Query
To dynamically generate this SQL Query
select NUMBER, REQUESTED_BY from SourceTable
where NUMBER = 404115
Table.SelectRows is your Where.
SelectColumns is your select
let
Source = ...,
filterByNum = 404115,
columnNames = {"NUMBER", "REQUESTED_BY"},
removedColumns = Table.SelectColumns(
Source, columnNames, MissingField.Error
),
// I used 'MissingField.Error' so you know right away
// if there's a typo or bug
// assuming you are comparing Source[NUMBER]
filteredTable = Table.SelectRows(
Source, each [NUMBER] = filterByNum
)
in
filteredTable

Powerquery - reference Excel cell value within SQL query?

I am trying to modify an excel worksheet that was given to me, with a connection to a SQL database that looks as follows:
select * from DB.AccountAssignments where Company_Code = '102'
How can I replace the static 102 value to reference a specific cell in Excel? For example, cell A1? The objective of course, being that when I change the 102 for a different value, the query will re-run without having to enter PowerQuery to edit the query it self each time.
NOTE: I found examples that involve filtering AFTER the query runs and pulls the data. However, the data source is HUGE so I need the Company Code parameter to be embedded within the query, so that the data brought into Powerquery is already filtered. That makes the difference between the query taking 5 seconds to run to 5 minutes to run.
I spent a couple hours attempting instructions on older posts, but have not been successful so far.
I had the same problem and it took me some time to understand how to implement Sharif's answer. So here are more detailed instructions based on the same idea:
Convert your cell into a named range (Formulas > Define Name)
Select the cell and go to Data > Get Data > From Other Sources > From Table/Range, which opens the Power Query Editor
Right-click on your cell value in the little preview table in the editor and select 'Drill Down'
Go to Home/File > Close & Load To (the 'To' is important here!). An 'Import Data' window pops up. Select 'Only create connection'.
Now you have a query parameter, that can be used in any other query.
Open the power query editor for your SQL query (Edit)
User the parameter in your query:
Source = Odbc.Query("dsn=SQLDSN", "select * from DB.AccountAssignments where Company_Code = " & NamedRangeCompanyCodeFromCell )
I got the error Expression.Error: We cannot apply operator & to types Text and Number. I solved that by changing the type of my query parameter: In the query of my parameter under Applied Steps > Changed Type, I changed Int64.Type to type text
Most likely, you will also need to give permission to run this query
Instead of creating a separate query parameter, it can also be created on the fly within the SQL query:
Open the Power Query Editor of your SQL query (Edit)
Open the advanced editor (Home > Advanced Editor)
Do all the necessary steps here, e.g.:
let
Params = Excel.CurrentWorkbook(){[Name="myNamedRange"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Params,{{"Column1", type text}}),
CodeFromCell = #"Changed Type"{0}[Column1],
Source = Odbc.Query("dsn=SQLDSN", "select * from DB.AccountAssignments where Company_Code = " & CodeFromCell)
in
Source
Convert cell A1 to Table from Range (Insert -> Table)
Name the table as param (or anything you like)
Use the below lines to use this table in your power query:
params = Excel.CurrentWorkbook(){[Name="params"]}[Content],
code = params{0}[value],
Use this in your SQL query:
select * from DB.AccountAssignments where Company_Code = code
Most likely you will have something similar to below line in your power query editor:
Source = Odbc.Query("dsn=SQLDSN", "select * from DB.AccountAssignments where Company_Code = " & code ),

Excel Power Query: Variables for Table Name

I'm trying to achieve something that seems like it should be fairly simple but I can't find an answer for... replace the name of a table or power query with a variable.
Currently trying to do this with a merge query so it would look something like this:
Table.NestedJoin(VARIABLE1,key1,VARIABLE2,key2,"Append",JoinKind.Inner)
Currently getting all sorts of errors no matter what I try...
Thank you!
// Edit:
Not really looking to do a function - hoping for users to utilize as easy as possible so they would be able to update a named table in the workbook, refresh, and then get a table as an output. Here is my current code - hopefully that'll help. My Region code replacements worked fine, but the Days replacements don't - I need each day (Monday-Thursday) to be replaced with my day variables (StartDay, Day2, etc.). Each of those has a separate text query referring back to the excel workbook inputs, and each of them should pull up a query based on the text (ex: StartDay = Monday so should pull the Monday query). This is the error I get, assuming that it is reading it as text "Monday" and not query Monday.
Expression.Error: We cannot convert the value "Monday" to type Table.
Details:
Value=Monday
Type=Type
let
ANDOriginCode = OriginRegion,
ANDDestinationCode = DestinationRegion,
ANDStartDay = StartDay,
ANDDay2 = Day2,
ANDDay3 = Day3,
ANDDay4 = Day4,
ANDDay5 = Day5,
Source = Table.NestedJoin(Monday,{"Tuesday Destination Region Code"},Tuesday,{"Tuesday Origin Region Code"},"Append1 (3)",JoinKind.Inner),
#"Filtered Rows1" = Table.SelectRows(Source, each [Monday Origin Region Code] = OriginRegion),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows1",{"ID", "Pickup Day of Week", "Delivery Day of Week"}),
#"Expanded Append1 (3)" = Table.ExpandTableColumn(#"Removed Columns", "Append1 (3)", {"Tuesday Origin Region Code", "Wednesday Destination Region Code", "Tuesday Projected Number of Loads"}, {"Tuesday Origin Region Code", "Wednesday Destination Region Code", "Tuesday Projected Number of Loads"}),
#"Merged Queries" = Table.NestedJoin(#"Expanded Append1 (3)",{"Wednesday Destination Region Code"},Wednesday,{"Wednesday Origin Region Code"},"Append1 (4)",JoinKind.Inner),
#"Expanded Append1 (4)" = Table.ExpandTableColumn(#"Merged Queries", "Append1 (4)", {"Wednesday Origin Region Code", "Thursday Destination Region Code", "Wednesday Projected Number of Loads"}, {"Wednesday Origin Region Code", "Thursday Destination Region Code", "Wednesday Projected Number of Loads"})
#"Merged Queries1" = Table.NestedJoin(#"Expanded Append1 (4)",{"Thursday Destination Region Code"},Thursday,{"Thursday Origin Region Code"},"Append1 (5)",JoinKind.Inner)
in
#"Merged Queries1"
This might help:
let
Source = (VARIABLE1 as table, VARIABLE2 as table) => Table.NestedJoin(VARIABLE1, Key1, VARIABLE2, Key1, "Append", JoinKind.Inner)
in
Source
You can use parameters for Key1 and Key2. The function will prompt you to select your tables.
You can invoke it from any other query with:
Function.Invoke(Merge,{Table1,Table2})
Replace Merge with whatever you named the first query above and replace Table1 and Table2 with your target tables.
In case you're thinking of it, I have not been able to figure out how to pass tables from parameters. When you do that, the value you enter is recognized as text--for instance, "Table" versus Table--so it won't work. I could not find any information on how to pass a table value, like Table, in a variable. Anyhow, I hope this helps at least a little.
I was searching for this, too!
I finally found it, thanks to Chris Webb at https://blog.crossjoin.co.uk/2015/02/06/expression-evaluate-in-power-querym/
The key is using Expression.Evaluate with #shared as the second argument.
If you define Query1 as
let
Source = 1 + 1
in
Source
Query2 as
let
Source = 15 * 10
in
Source
define pIndex as a parameter that is "1" or "2", and
define QuerySwitch as
Expression.Evaluate("Query" & pIndex, #shared)
then QuerySwitch will return
2 when pIndex is "1"
150 when pIndex is "2"
My example:
I have a query QueryThatTakesFiveMinutes that
other queries use, and
writes to an Excel table (also named "QueryThatTakesFiveMinutes")
If I define a query "QueryThatTakesFiveMinutes Cached" by moving my cursor to the output QueryThatTakesFiveMinutes table in Excel and creating a new query from that table then, when I'm testing, I can change all the queries that use QueryThatTakesFiveMinutes to instead use #"QueryThatTakesFiveMinutes cached" and test downstream computation without waiting five minutes every time. Then I just need to remember to change it back when I'm ready.
But that was annoying.
I created a named range in Excel called "ProductionMode" that pointed to a specific cell that holds a value of either TRUE or FALSE
In Power-Query, I defined a very handy power query function called fNamedCellValue as
(rangeName as text) => Excel.CurrentWorkbook(){[Name=rangeName ]}[Content]{0}[Column1]
so that I can define a "ProductionMode" query as
fGetNamedCellValue("ProductionMode")
I use this in a way that's similar to the Index parameter above, but this way I can edit it via Excel.
When I defined "modeQueryThatTakesFiveMinutes" as
if ProductionMode then QueryThatTakesFiveMinutes else #"QueryThatTakesFiveMinutes Cached"
and changed all queries that use QueryThatTakesFiveMinutes to use modeQueryThatTakesFiveMinutes instead, I was very surprised to find that both QueryThatTakesFiveMinutes and #"QueryThatTakesFiveMinutes Cached" were evaluated and it didn't save any time at all!
So then after searching, being overjoyed to find your question only to realize it wasn't answered, then finding Chris Webb's article, I tried redefining modeQueryThatTakesFiveMinutes as
Expression.Evaluate(
if ProductionMode then
"QueryThatTakesFiveMinutes"
else
"#""QueryThatTakesFiveMinutes Cached""",
#shared
)
Unfortunately, instead of working, I got an error of
Formula.Firewall: Query 'modeQueryThatTakesFiveMinutes' references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
However, I found a way around this, too, by putting the offending code within a function that the consuming query executes.
Deleting ProductionMode and defining a new query fProductionMode of
() => fGetNamedCellValue("ProductionMode") as logical
now doesn't return true or false, it returns a function that will return true or false when evaluated. Why is one legal and the other isn't? I don't know, but it is! Change the definition of modeQueryThatTakesFiveMinutes to
Expression.Evaluate(
if fProductionMode() then
"QueryThatTakesFiveMinutes"
else
"#""QueryThatTakesFiveMinutes Cached""",
#shared
)
and it works!

Trying to pull data from a SODA API into Excel

The API call looks like this:
https://data.edmonton.ca/resource/3pdp-qp95.json?house_number=10008&street_name=103%20STREET%20NW
and returns data in json:
[{"account_number":"3070208","garage":"N","house_number":"10008","latitude":"53.539158992619","longitude":"-113.497760691896","neighbourhood":"DOWNTOWN","street_name":"103 STREET NW","tax_class":"Non Residential","total_asmt":"1717000"}]
I have an excel table with specific house_number and street_name pairs and I want to capture the total_asmt column for each pair.
I've been able to create a power query which pulls the very first data point into a new sheet:
let
Parameter = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Removed Other Columns" = Table.SelectColumns(Parameter,{"house_number", "street_name"}),
X = #"Removed Other Columns"[house_number]{0},
Y = #"Removed Other Columns"[street_name]{0},
Source = Json.Document(Web.Contents("https://data.edmonton.ca/resource/3pdp-qp95.json?house_number="& X &"&street_name=" & Y)),
in
Source
I can't figure out how to iterate through all the value I have in X and Y or how to capture specific rows from the JSON data. Any help would be appreciated!
Thanks,
Aaleem
I think your best best is to not do it.
Why are you wasting your time scraping this data one address at a time when you could have the entire city's data in under a minute.
JSON: https://data.edmonton.ca/resource/3pdp-qp95.json
CSV: https://data.edmonton.ca/api/views/q7d6-ambg/rows.csv?accessType=DOWNLOAD
XML: https://data.edmonton.ca/api/views/q7d6-ambg/rows.xml?accessType=DOWNLOAD
...among others. Heck, they even have !
And when you're done with that one, they have a few hundred other interesting datasets.
The trick was to create a function inside powerquery, and then use the query as part of a table. Create the function as below and then under the data tab select your table using "From Table/Range" from there it is pretty straight forward.
let a_value= (x as number,y as text)=> //this creates the function
let //this is essentially the query I wanted with some minor changes from above
x_text = Number.ToText(x, "D", ""),
Source = Json.Document(Web.Contents("https://data.edmonton.ca/resource/3pdp-qp95.json?house_number="&x_text&"&street_name="&y)),
Source1 = Source{0},
total_asmt = Source1[total_asmt]
in
total_asmt
in a_value //closes the function

Where is an option set value's description stored in CRM 2011

I am working on a report that pulls some data from CRM and for some reason the real value text I need is in the description of the option set choice. For the life of me I can not find it in the entity's StringMap's, or attributes's views. Help!!
I initially read the question incorrectly which prompted me to go down the wrong path. To get the "Description" use the following query:
SELECT DISTINCT ATTR.NAME, LOCLAB.LABEL AS DESCRIPTION
FROM [ORG_MSCRM].[MetadataSchema].[Entity] ENT
LEFT JOIN [ORG_MSCRM].[METADATASCHEMA].[ATTRIBUTE] ATTR
ON ENT.ENTITYID = ATTR.ENTITYID
LEFT JOIN [ORG_MSCRM].[METADATASCHEMA].[ATTRIBUTEPICKLISTVALUE] ATTRPICK
ON ATTR.OPTIONSETID = ATTRPICK.OPTIONSETID
LEFT JOIN [ORG_MSCRM].[METADATASCHEMA].[LOCALIZEDLABEL] LOCLAB
ON LOCLAB.OBJECTID = ATTRPICK.ATTRIBUTEPICKLISTVALUEID
WHERE ENT.OBJECTTYPECODE ='2' --contact
AND ATTR.NAME = 'GENDERCODE' --attributename
AND LOCLAB.OBJECTCOLUMNNAME = 'DESCRIPTION'

Resources