NOTE: This post was written before Data Explorer was renamed as Power Query. All of the content is still relevant to Power Query.
One of the first questions I get asked after showing someone PowerPivot for the first time is “Can I add new data to a PowerPivot table that already has data in it?”. Out of the box, of course, the answer is no: when you process a table in PowerPivot you have to reload all the data from your data source, you can’t just append new data (unless you’re using copy/paste to load data, which isn’t a good idea). However, there are a lot of self-service BI scenarios where the ability to do this would be extremely useful: for example, you might want to scrape stock quotes from a web page every day and then, in an Excel workbook, accumulate that data in a table so you can analyse historical stock prices with PowerPivot. I ran into a scenario very much like this last week and I thought that Data Explorer should be able to help here. It can, but it’s not obvious how to do it – hence this blog post!
Here’s a super-simple example of how to accumulate data in a table then. Let’s start with a csv file that contains the following data:
Product,Sales
Apples,1
Oranges,2
It’s straightforward to import this data into Excel using Data Explorer and the ‘From csv’ data source:
Here’s the code that Data Explorer generates:
let
Source = Csv.Document(File.Contents("C:\InputData.csv")),
FirstRowAsHeader = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(FirstRowAsHeader,
{{"Product", type text}, {"Sales", type number}})
in
ChangedType
Now, let’s imagine that you want to keep the data from this file in Excel and every time you click Refresh in Data Explorer you add the data from the file onto the end of the existing data you’ve already captured. The first thing you’ll probably want to do in this scenario is add a new column to the data that gives the date and time that the data was loaded, and you can do that quite easily in Data Explorer using the DateTimeZone.UtcNow() function as follows:
Table.AddColumn(ChangedType, “Load Date”, each DateTimeZone.UtcNow())
Data Explorer has functionality to append the data from one query onto the end of another query, but the problem you have to solve now is that when you click Refresh you want the new data to be appended onto the end of the data that has already been collected. It’s a recursive scenario not unlike the one I grappled with here. The solution to this problem is to first of all load the data into the PowerPivot (ie what we should be calling the Excel Data Model now) by clicking on the Load To Data Model link in the Data Explorer query pane:
Then, on a new sheet, create an Excel query table that returns all the data from the PowerPivot table that you’ve just loaded data into. Kasper shows how to do this here; there’s no need for any special DAX, you just need to connect to the PowerPivot table in the Existing Connections dialog:
At this point you should have two tables on two sheets that contain the same data. The next step is to modify the original Data Explorer query so that it contains a new step that appends data from the table you’ve just created (ie the table getting the data from PowerPivot) onto the data from the csv file. This can be done with three new steps, first to get the data from the new Excel table:
Excel.CurrentWorkbook(){[Name="ExistingData"]}[Content]
Then to make sure the Load Date is treated as a DateTimeZone type:
Table.TransformColumnTypes(GetExistingData,{{“Load Date”, type datetimezone}})
Then finally to combine the two tables:
Table.Combine({ChangedType1,InsertedCustom})
Now, whenever you Refresh your Data Explorer query, you will see the data from the csv file appended to the data that has already been loaded:
Here’s the complete code:
let
Source = Csv.Document(File.Contents("C:\InputData.csv")),
FirstRowAsHeader = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(FirstRowAsHeader,
{{"Product", type text}, {"Sales", type number}}),
InsertedCustom = Table.AddColumn(ChangedType, "Load Date", each DateTimeZone.UtcNow()),
Custom1 = Excel.CurrentWorkbook(){[Name="Table_Input_Data"]}[Content],
ChangedType1 = Table.TransformColumnTypes(Custom1,{{"Load Date", type datetimezone}}),
Custom2 = Table.Combine({ChangedType1,InsertedCustom})
in
Custom2
Now as I said, this is just a super-simple example and in the real world you’d need extra functionality to do things like delete rows you’ve already loaded and so on; but that’s all doable I think. It’s also worth mentioning that I encountered some strange errors and behaviour when implementing this, partly due to Data Explorer still being in preview I guess, so if you want to recreate this query you’ll need to follow my instructions exactly.
You can download the sample workbook here, and the csv file here.