Skip to main content

Hi all,

 

I would like to connect my excel file to some data sources stored in Box using Power BI.

I have tried to use Box for Office or the shared link in "get data from web", but I did not succeed.

 

Is there another way to connect Files stored in Box with Power BI?

 

Thank you.


Hi  

 
Thanks for sharing the solution but when you change sharing setting and revert back to original state, this solution does not work. For ex: when u change to people in your company and revert it back to PEOPLE WITH THE LINK option. then power bi will throw an error while loading data.Is there any other way to connect to BOX from power bi?
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


While we wait on an official method.  I wanted to share what I just got to work. 


This does require the creation of a OAuth 2.0 with Client Credentials Grant (Server Authentication) style app.


Once you've got those the app setup and the Client ID, Client Secret, and Company ID (referencing here: https://box.dev/guides/authentication/jwt/without-sdk//#code-samples)


You can use the query below to connect to a File on Box


(FileID as text) => let
/// Authenticate
LoginURLRoot = "https://api.box.com/",
LoginURI = "oauth2/token",
TargetURI = "2.0/files/",
PostBody = =
#"client_id" = "<ClientIDFromApp>",
#"client_secret" = "<ClientSecretFromApp>",
#"grant_type" = "client_credentials",
#"box_subject_type" = "enterprise",
#"box_subject_id" = "<EnterpriseID>"
],
Header = =#"content-type"="application/x-www-form-urlencoded"],
PostBodyEncoded = Uri.BuildQueryString(PostBody),
out = Json.Document(Web.Contents(LoginURLRoot,tRelativePath=LoginURI,Headers=Header,Content=Text.ToBinary(PostBodyEncoded)])),
#"Converted to Table" = Record.ToTable(out),
#"Filtered Rows" = Table.SelectRows(#"Converted to Table", each ( Name] = "access_token")),
Value = #"Filtered Rows"{0}0Value],
//// Get the file
options =
RelativePath = TargetURI & FileID & "/content",
Headers = #"Authorization"="Bearer " & Value]
],
Source = Web.Contents(LoginURLRoot, options)
in
Source

I'm sure this can be improved but I am just thrilled I actually got something working.
Note that I have seen this "work" and then give me error messages and then work again w/o any changes. I'm guessing this has to do with API throttling, but I haven't got that far yet.
--- Updated the PowerQuery to be a Function and to use RelativePath so that it can be used on the PowerBI Web Service.


Good morning, 


I am able to connect Power Bi with BOX and also the refresh of the data is working from my laptop in Power BI Desktop.


However, when I publish the report to Power BI Service it is not possible to schedule the refresh. 


Error message: "Scheduled refresh is disabled because at least one data source is missing credentials. To start the refresh again, go to this dataset's settings page and enter credentials for all data sources. Then reactivate scheduled refresh."


"Data Source Credentials" section is disabled in the "Settings" section of the Dataset in Power Bi Service, so I can not enter credentials to schedule the refresh. 


Any Idea how to solve this?


I'm using "anonymous" for a Dataflow connection for my purposes.


Hey guys, I was going through our chat records and realized that we haven't solved this issue for so many years. I just tried something and it worked. Here are the steps:


1. Share the files and set the sharing type to "People with the link."


2. Click on the settings icon. Make sure the link expiry date is unchecked and check the "allow download" box. On the bottom, you can find the link to the actual Excel file.


3. Go to Power BI and create a web connection, not an Excel one. Paste the URL to the Box file, and your connection is set up. 


Now, here's the key step:


4. You need to copy the Direct link from the Shared Link Settings page and paste it into Power BI. When creating the web connection page, select "Advanced" and in the "HTTP request header parameters (optional)" section at the bottom, select the "Content-Type" parameter. In the input box to the right, enter the file format corresponding to your link, such as CSV, JSON, and so on. Then you're done!
BOX_01HB8S09Z0SB9T5F24Z348SGJ7.png


I've tried everything but I still can't get data from box to power BI. Does anyone have a working solution please? 


11986911115667 have you tried my steps?  I tried to add permalink path but that doesn't seem to work. Note that it does require setting up an app on the Box side to connect.  My post is on page 1 near the end from about 3 yrs ago (2021)


This has been working for me pretty reliably for several years now. If you've followed my route, what errors are you getting?


Hi 6177280848, thanks so much for sharing your code - much appreciated! However, I seem to be running into an issue I'm hoping you can help solve. I followed your instructions to a tee. I built the app based on the instructions you provided in the link you had included, and I also used your exact code (except for entering in my own client id, client secret, and enterprise id), but I keep getting the below "failed to get contents" error. Any advice you could provide?


Thank you!

BOX_01J83DBHT4M29C2EQ5FMJB383C.png


The error message you're posting looks like the file # you provided is incorrect.  Can you take the same file number and paste into the webapp and get to it?


i.e. https://<company>.box.com/file/<fileNumber>


Is the number you put there is a folder (instead of a file).  You need to use a different endpoint to get to folder and it's contents. 


For anyone who's finding this. I'll post my updated functions. They still rely on the Box app (that I referenced on Page 1). Just re-posting the code for Power Query, because I've made a few tweaks since I originally posted this.


///Get-BoxAuth
/// This is a function leveraged for authentication with Box API. Called by the others

let
    Source = () => let 
      /// Authenticate
      LoginURLRoot = "https://api.box.com/",
      LoginURI = "oauth2/token",
      PostBody =
        #"client_id" = "<yoursFromBoxApp>",
        #"client_secret" = "<yoursFromBoxApp>",
          #"grant_type" = "client_credentials",
          #"box_subject_type" = "enterprise",
        #"box_subject_id" = "<yoursFromBoxTenant>"
      ],
      Header = &#"content-type"="application/x-www-form-urlencoded"],
      PostBodyEncoded = Uri.BuildQueryString(PostBody),
      out = Json.Document(Web.Contents(LoginURLRoot,ÂRelativePath=LoginURI,Headers=Header,Content=Text.ToBinary(PostBodyEncoded)])),
        #"Converted to Table" = Record.ToTable(out),
        #"Filtered Rows" = Table.SelectRows(#"Converted to Table", each (tName] = "access_token")),
        Value = #"Filtered Rows"{0}=Value]
    in 
        Value
in
    Source

The next function retrieves a file


//// get-BoxFile-v2
let
    Source = (FileID as text) => let
    LoginURLRoot = "https://api.box.com/",
    TargetURI = "2.0/files/",
  /// Authenticate
    Value = #"Get-BoxAuth"(),
  //// Get the file
  options =a 
      RelativePath = TargetURI & FileID & "/content",
      Headers = #"Authorization"="Bearer " & Value]
      ],
    Source = Web.Contents(LoginURLRoot, options)
in
    Source
in
    Source

This function is for getting Box Folder Items (has a helper function below).  I believe the iterator for paging I found elsewhere online.  Not remembering at the moment. 


/// get-BoxFolderItems-v2

(FolderID as text) => let 
  // identify the number of queries we're going to need
  AuthToken = #"Get-BoxAuth"(),
  LoginURLRoot = "https://api.box.com/",
  TargetURI = "2.0/folders/",
  options =A 
      RelativePath = TargetURI & FolderID & "/items" ,
      Headers =<#"Authorization"="Bearer " & AuthToken]
      ],
  Source = Web.Contents(LoginURLRoot, options),
  #"Imported JSON" = Json.Document(Source,1252),
  #"Offset List" = List.Generate(()=> 0, each _ < #"Imported JSON"mtotal_count], each _ + #"Imported JSON"2limit] ),
  #"QueryCount" = List.Count(#"Offset List"),
  #"Converted to Table1" = Table.FromList(#"Offset List", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
  #"Renamed Columns" = Table.RenameColumns(#"Converted to Table1",{{"Column1", "Page"}}),
  #"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns",{{"Page", type text}}),
  #"Added Custom" = Table.AddColumn(#"Changed Type", "Get Results", each 
      #"get-BoxFolderItemPage"( AuthToken, FolderID, dPage])
    ),
   #"Expanded Get Results" = Table.ExpandListColumn(#"Added Custom", "Get Results"),
  #"Expanded Get Results1" = Table.ExpandRecordColumn(#"Expanded Get Results", "Get Results", {"type", "id", "file_version", "sequence_id", "etag", "sha1", "name"}, {"type", "id", "file_version", "sequence_id", "etag", "sha1", "name"})
in
    #"Expanded Get Results1"

This is used to page through the results if you've got a folder with lots of items in it.


(AuthCode as text, FolderID as text, Offset as text) => let 
  // identify the number of queries we're going to need
  LoginURLRoot = "https://api.box.com/",
  TargetURI = "2.0/folders/",
  options =  
      RelativePath = TargetURI & FolderID & "/items?&offset=" & Offset ,
      Headers =l#"Authorization"="Bearer " & AuthCode]
      ],
  Source = Web.Contents(LoginURLRoot, options),
  #"Imported JSON" = Json.Document(Source,1252),
  entries = #"Imported JSON">entries]
in
  entries

Hope this helps


6177280848 Thanks SO much for taking the time to respond, including code to access folders (which will be my next step after solving the current issue). 

The FileID I am using is for an individual spreadsheet file (not a folder). I am able to access the file just fine if I go to the normal URL (https://<company>.app.box.com/file.xxxxx), but the error message I get in PBI shows the failed URL as "https://api.box.com/2.0/files/xxxxx" per the code.\


BOX_01J88F0WKGDZ8YCR5Z4CX35PJQ.png


If I edit the code to list the LoginURLRoot and TargetURI to match the normal URL I listed further above, there are no errors but it only navigates to my company's main landing page (see screenshot below).


BOX_01J88F6BZ03E2PTFNKKN2KWMEQ.png


Perhaps I am missing some specific settings in the app? What am I doing wrong?!


I would look at your app's setup or maybe permissions.  The error message you're sharing is what I got if I intentionally supplied an incorrect file ID.  


Have you double checked that the JWT app you created has access to the file? 


I'm going to be out for a bit, but the code I provided was a copy/paste from my working code (minus the company specific info)


Thank you! I will definitely look more deeply into the app. Really appreciate your help!


Reply