giovedì 3 novembre 2022

D365FFO - Salvare SSRS report come file PDF e caricarlo su una Azure Storage

In questo post vediamo come generare il file PDF di un report (Fattura a testo libero in questo caso) e fare l'upload su di una Azure storage.

Ho preso spunto da questo post:

https://meritsolutions.com/render-report-memory-stream-d365-aka-ax7/

ed ho aggiunto la parte per l'upload su Azure:

 using Microsoft.Azure;  
 using Microsoft.WindowsAzure.Storage;  
 using Microsoft.WindowsAzure.Storage.Blob;  
 using Microsoft.WindowsAzure.Storage.File;  
   
 class LILTestClassPDFUpload  
 {  
   public static void main(Args _args)  
   {  
     Args args;  
     CustInvoiceJour CustInvoiceJour;  
   
     select firstonly    CustInvoiceJour  
       where CustInvoiceJour.InvoiceId == "000051"  
                && CustInvoiceJour.SalesId == "";  
   
     Filename fileName = strFmt("%1_%2%3",curExt(),CustInvoiceJour.InvoiceId,".pdf");  
     FreeTextInvoiceController controller = new FreeTextInvoiceController();  
     FreeTextInvoiceContract contract = new FreeTextInvoiceContract();  
     SRSPrintDestinationSettings settings;  
     Array arrayFiles;  
     System.Byte[] reportBytes = new System.Byte[0]();  
     SRSProxy srsProxy;  
     SRSReportRunService srsReportRunService = new SrsReportRunService();  
     Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;  
     Map reportParametersMap;  
     SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();  
             
           //esempio:  
           //mystorageAccountName.file.core.windows.net\myRootFolder\mySubFolder  
     str           accountName   = "mystorageAccountName";   
     str           key       = "Er0kY1KUDX9/D3tunAD6twYaBT6ux3nJp...etc..";  
     str           rootFolder   = "myRootFolder";  
     str           custLinkFolder = "mySubFolder";  
     ;  
   
     args = new Args();  
     args.record(CustInvoiceJour);  
     contract.parmCustInvoiceJourRecId(CustInvoiceJour.RecId);  
   
     // Provide details to controller and add contract  
     controller.parmArgs(args);  
     controller.parmReportName(ssrsReportStr(TTL_FreeTextInvoice, Report));  
     controller.parmShowDialog(false);  
     controller.parmLoadFromSysLastValue(false);  
     controller.parmReportContract().parmRdpContract(contract);  
     // Provide printer settings  
     settings = controller.parmReportContract().parmPrintSettings();  
     settings.printMediumType(SRSPrintMediumType::File);  
     settings.fileName(fileName);  
     settings.fileFormat(SRSReportFileFormat::PDF);  
   
     // Below is a part of code responsible for rendering the report  
     controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());  
     controller.parmReportContract().parmReportExecutionInfo(executionInfo);  
   
     srsReportRunService.getReportDataContract(controller.parmreportcontract().parmReportName());  
     srsReportRunService.preRunReport(controller.parmreportcontract());  
     reportParametersMap = srsReportRunService.createParamMapFromContract(controller.parmReportContract());  
     parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);  
   
     srsProxy = SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig());  
     // Actual rendering to byte array  
     reportBytes = srsproxy.renderReportToByteArray(controller.parmreportcontract().parmreportpath(),  
       parameterValueArray,  
       settings.fileFormat(),  
       settings.deviceinfo());  
   
           //upload file...  
     if (reportBytes)  
     {  
       System.IO.MemoryStream stream = new System.IO.MemoryStream(reportBytes);  
   
       str filetemppath = File::SendFileToTempStore(stream,fileName);  
       System.IO.Stream fileStream = File::UseFileFromURL(filetemppath);  
   
       var storageCredentials = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(accountName, key);  
       CloudStorageAccount storageAccount = new Microsoft.WindowsAzure.Storage.CloudStorageAccount(storageCredentials, true);  
       CloudFileClient fileClient = storageAccount.CreateCloudFileClient();  
       CloudFileShare share = fileClient.GetShareReference(rootFolder);  
                  
       if (share.Exists(null, null))  
       {  
         CloudFileDirectory rootDir = share.GetRootDirectoryReference();  
         CloudFileDirectory fileDir = rootDir.GetDirectoryReference(custLinkFolder);  
                       
         if (fileDir.Exists(null, null))  
         {  
           CloudFile cfile = fileDir.GetFileReference(fileName);  
           
           if (cfile.Exists(null, null))  
           {  
             throw error("@SYS95668");  
           }  
           else  
           {  
             str a = File::SendFileToTempStore(stream,fileName);  
             try  
             {  
               cfile.UploadFromStream(fileStream,null,null,null);  
             }  
             catch(Exception::Error)  
             {  
               throw error("Error during file upload");  
             }  
           }  
         }  
       }  
     }  
   }  
 }