Azurearch Tech

Export excel file from Power BI paginated reports

Prerequisite

Power Bi authentication using masteruser(using username and password ) OR Serviceprincipal(tenantId, application Id and application secret)

Export power bi reports into excel format using azure function .Net core V2.

function App configuration file

Http trigger azure Function

 [FunctionName("ReportUtilityFunction")]
        public IActionResult Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            

PowerBiReportExpoter powerBiReportExpoter = new 

PowerBiReportExpoter(_configurationManager, log, _powerBiClientConnector);
            

powerBiReportExpoter.ExportPowerBIReport();

       return new OkObjectResult(string.Empty);

There are steps to export power bi reports

Get report export Id

Polling

Get stream object and convert into excel.

using Microsoft.Extensions.Logging;
using Microsoft.PowerBI.Api;
using Microsoft.PowerBI.Api.Models;
using Microsoft.Rest;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace ReportUtilityFunctionApp
{
    public class PowerBiReportExpoter
    {
        private readonly IConfigurationManager _configurationManager;
        private readonly IPowerBiClientConnector _powerBiClientConnector;
        private readonly ILogger _log;
        public PowerBiReportExpoter(IConfigurationManager iConfigurationManager, ILogger log, IPowerBiClientConnector powerBiClientConnector)
        {
            _configurationManager = iConfigurationManager;
            _powerBiClientConnector = powerBiClientConnector;
            _log = log;
        }
        
        public async Task<ExportedFile> ExportPowerBIReport(ReportDesign report,CancellationToken token,IList<string> pageNames = null,  /* Get the page names from the GetPages REST API */string urlFilter = null)
        {
            const int c_secToMillisec = 1000;
            try
            {
                Export export = null;
                int retryAttempt = 1;
                do
                {
                    var exportId = await PostExportRequest(report);
                    var httpMessage =  await PollExportRequest(report.PowerBiReportId, exportId, Convert.ToInt16(_configurationManager.PollingTimeOutInMinutes), token);
                    export = httpMessage.Body;
                    if (export == null)
                    {
                        // Error, failure in exporting the report
                        _log.LogInformation($"{DateTime.UtcNow}: Error, failure in exporting the report");
                        return null;
                    }
                    if (export.Status == ExportState.Failed)
                    {
                        // Some failure cases indicate that the system is currently busy. The entire export operation can be retried after a certain delay
                        // In such cases the recommended waiting time before retrying the entire export operation can be found in the RetryAfter header
                        var retryAfter = httpMessage.Response.Headers.RetryAfter;
                        if (retryAfter == null)
                        {
                            // Failed state with no RetryAfter header indicates that the export failed permanently
                            _log.LogInformation($"{DateTime.UtcNow} : No RetryAfter header, export failed permanently");
                            return null;
                        }

                        var retryAfterInSec = retryAfter.Delta.Value.Seconds;
                        await Task.Delay(retryAfterInSec * c_secToMillisec);
                    }
                }
                while (export.Status != ExportState.Succeeded && retryAttempt++ < Convert.ToInt16(_configurationManager.MaxNumberOfRetries));

                if (export.Status != ExportState.Succeeded)
                {
                    // Error, failure in exporting the report
                    _log.LogInformation($"{DateTime.UtcNow} : Error, failure in exporting the report");
                    return null;
                }

                if (export.Status == ExportState.Succeeded)
                {
                    
                    _log.LogInformation($"{DateTime.UtcNow} : Report has been exported successfully");
                  
                }

                var exportedFile = await GetExportedFile(report.PowerBiReportId, export);

                return exportedFile;
            }
            catch
            {
                // Error handling
                throw;
            }
        }
        private async Task<ExportedFile> GetExportedFile(Guid reportId,Export export /* Get from the PollExportRequest response */)
        {
            if (export.Status == ExportState.Succeeded)
            {
                // The 'Client' object is an instance of the Power BI .NET SDK
                var fileStream = await _powerBiClientConnector.GetToken(_configurationManager).Reports.GetFileOfExportToFileAsync(_configurationManager.WorkspaceId, reportId, export.Id);
                using (MemoryStream ms = new MemoryStream())
                {
                    fileStream.CopyTo(ms);

                    return new ExportedFile
                    {
                        Filebyte = ms.ToArray(),
                        FileSuffix = export.ResourceFileExtension,
                    };
                }  
            }
            return null;
        }
        
        public class ExportedFile
        {
            public byte[] Filebyte;
            public string FileSuffix;
        }
        private async Task<HttpOperationResponse<Export>> PollExportRequest(Guid reportId,string exportId /* Get from the PostExportRequest response */,int timeOutInMinutes,CancellationToken token)
        {
            HttpOperationResponse<Export> httpMessage = null;
            Export exportStatus = null;
            DateTime startTime = DateTime.UtcNow;
            const int c_secToMillisec = 1000;
            do
            {
                if (DateTime.UtcNow.Subtract(startTime).TotalMinutes > timeOutInMinutes || token.IsCancellationRequested)
                {
                    // Error handling for timeout and cancellations 
                    _log.LogInformation($"{DateTime.UtcNow} : Timeout and cancellations");
                    return null;
                }

                // The 'Client' object is an instance of the Power BI .NET SDK
                httpMessage =  await _powerBiClientConnector.GetToken(_configurationManager).Reports.GetExportToFileStatusInGroupWithHttpMessagesAsync(_configurationManager.WorkspaceId, reportId, exportId);
                exportStatus = httpMessage.Body;

                // You can track the export progress using the PercentComplete that's part of the response
                _log.LogInformation(string.Format("{0} (Percent Complete : {1}%)", exportStatus.Status.ToString(), exportStatus.PercentComplete));
                if (exportStatus.Status == ExportState.Running || exportStatus.Status == ExportState.NotStarted)
                {
                    // The recommended waiting time between polling requests can be found in the RetryAfter header
                    // Note that this header is not always populated
                    var retryAfter = httpMessage.Response.Headers.RetryAfter;
                    var retryAfterInSec = retryAfter.Delta.Value.Seconds;
                    await Task.Delay(retryAfterInSec * c_secToMillisec);
                }
            }
            // While not in a terminal state, keep polling
            while (exportStatus.Status != ExportState.Succeeded && exportStatus.Status != ExportState.Failed);

            return httpMessage;
        }

        public async Task<string> PostExportRequest(ReportDesign report)
        {
            
            var powerBIReportExportConfiguration = new PowerBIReportExportConfiguration
            {
                Settings = new ExportReportSettings
                {
                    Locale = "en-us",
                },
                // Note that page names differ from the page display names
                // To get the page names use the GetPages REST API
                // Pages = pageNames?.Select(pn => new ExportReportPage(Name = pn)).ToList(),
                // ReportLevelFilters collection needs to be instantiated explicitly
                // ReportLevelFilters = !string.IsNullOrEmpty(urlFilter) ? new List<ExportFilter>() { new ExportFilter(urlFilter) } : null,

            };
            PaginatedReportExportConfiguration paginatedReportExportConfiguration = new PaginatedReportExportConfiguration
            {
                ParameterValues = report.ParameterValues

            };

            var exportRequest = new ExportReportRequest
            {
                Format = FileFormat.XLSX,//_configurationManager.ReportFormat,
                PaginatedReportConfiguration = paginatedReportExportConfiguration
                //PowerBIReportConfiguration = powerBIReportExportConfiguration,
            };

            // The 'Client' object is an instance of the Power BI .NET SDK
            var export = await _powerBiClientConnector.GetToken(_configurationManager).Reports.ExportToFileInGroupAsync(_configurationManager.WorkspaceId, report.PowerBiReportId, exportRequest);

            // Save the export ID, you'll need it for polling and getting the exported file
            return export.Id;
        }

        

    }
}

Using azure function activity, call above http trigger function from ADF pipeline.

Exit mobile version