web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Unanswered

How to improve performance in creating SSRS reports with X++ ?

(1) ShareShare
ReportReport
Posted on by 80

Hello community,

I’m working on an integration where I create free text invoices from data pulled from a third-party source. After generating and posting the invoices, I generate a custom SSRS report (as a PDF) and attach it to each free text invoice. However, this final step is taking a significant amount of time, especially as I’m processing a large volume of invoices.

Could anyone suggest improvements to my code or offer alternative methods to speed up this part of the process? Below is the code I’m using to generate the PDF and attach it to the invoice.

Thank you in advance for your help!

 
    public void generateAndAttachPDF(NPLOracleSupportHeader headerRecord)
    {
        CustInvoiceJour custInvoiceJour;
        CustInvoiceTable custInvoiceTable;
        PrintMgmtReportFormatName printMgmtReportFormatName;
        FreeTextInvoiceContract freeTextInvoiceContract = new FreeTextInvoiceContract();
        SrsReportRunController srsReportRunController;
        SRSPrintDestinationSettings printerSettings;
        System.Byte[] reportBytes;
        SrsReportRunService srsReportRunService;
        SRSProxy srsProxy;
        Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray;
        Map reportParametersMap;
        str fileName = "";
        SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo();

        // Fetch the invoice journal and table records
        select firstonly custInvoiceJour
            where custInvoiceJour.InvoiceId == headerRecord.NPLOracleInvoiceIdDynamics
            && custInvoiceJour.NPLInvoiceId == headerRecord.NPLOracleInvoiceId;

        if (!custInvoiceJour)
        {
            error("Invoice not found.");
            return;
        }

        select firstonly custInvoiceTable
            where custInvoiceTable.InvoiceId == custInvoiceJour.InvoiceId;

        if (!custInvoiceTable)
        {
            error("Invoice table record not found.");
            return;
        }

        // Set up the file name and print management report format
        fileName = custInvoiceJour.InvoiceId + ".pdf";
        printMgmtReportFormatName = ssrsReportStr(CustomFormatReport, Report);

        // Initialize the report contract with the invoice record ID
        freeTextInvoiceContract.parmCustInvoiceJourRecId(custInvoiceJour.RecId);

        // Initialize the report controller once
        srsReportRunController = new SrsReportRunController();
        srsReportRunController.parmReportName(printMgmtReportFormatName);
        srsReportRunController.parmExecutionMode(SysOperationExecutionMode::Asynchronous);
        srsReportRunController.parmShowDialog(false);
        srsReportRunController.parmLoadFromSysLastValue(false);
        srsReportRunController.parmReportContract().parmRdpContract(freeTextInvoiceContract);

        // Configure print settings to generate the PDF
        printerSettings = srsReportRunController.parmReportContract().parmPrintSettings();
        printerSettings.printMediumType(SRSPrintMediumType::File);
        printerSettings.fileFormat(SRSReportFileFormat::PDF);
        printerSettings.fileName(fileName);
        printerSettings.overwriteFile(true);

        try
        {
            // render the report
            srsReportRunService = new SRSReportRunService();
            srsReportRunController.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration());
            srsReportRunController.parmReportContract().parmReportExecutionInfo(executionInfo);
            srsReportRunService.getReportDataContract(srsReportRunController.parmReportContract().parmReportName());
            srsReportRunService.preRunReport(srsReportRunController.parmReportContract());
            srsReportRunService.parmIsInBatch(true);
            
            reportParametersMap = srsReportRunService.createParamMapFromContract(srsReportRunController.parmReportContract());
            parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap);

            srsProxy = SRSProxy::constructWithConfiguration(srsReportRunController.parmReportContract().parmReportServerConfig());

            // render report to byte array
            reportBytes = srsProxy.renderReportToByteArray(
                srsReportRunController.parmReportContract().parmReportPath(),
                parameterValueArray,
                printerSettings.fileFormat(),
                printerSettings.deviceInfo()
            );

            // Attach the generated PDF to the invoice
            if (reportBytes)
            {
                this.attachPDFToInvoice(custInvoiceTable, reportBytes, fileName);
            }
            else
            {
                error("Failed to render the report to a byte array.");
            }
        }
        catch (Exception::Error)
        {
            error("An error occurred during the report generation.");
        }
    }

    public void attachPDFToInvoice(CustInvoiceTable custInvoiceTable, System.Byte[] reportBytes, str fileName)
    {
        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(reportBytes);
        DocuRef docuRef;

        // Attach the PDF in a transaction
        ttsBegin;
        docuRef = DocumentManagement::attachFile(
            custInvoiceTable.TableId,
            custInvoiceTable.RecId,
            custInvoiceTable.DataAreaId,
            DocuType::typeFile(),
            memoryStream,
            fileName,
            System.Web.MimeMapping::GetMimeMapping(fileName),
            custInvoiceTable.InvoiceId
        );
        ttsCommit;
    }
 
 
I have the same question (0)
  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at
    You'll need a better idea about the problem before you can fix it.
     
    Looking at a small part of the solution and trying to guess performance problems isn't a good approach. Instead, measure what takes the most time. The slowest part of report printing usually is the data preparation, which may (but doesn't have to) be your case too. Note that such code isn't shown above.
     
     
  • Mario C Profile Picture
    80 on at

    Hello Martin,

    I’ve extended the data provider class for the free text invoice (FreeTextInvoiceDP), where I added some custom logic and populated the FreeTextInvoiceHeaderFooterTmp and FreeTextInvoiceTmp tables. Is this what you meant by the data preparation part? other than that I’ve just created a custom SSRS report using those two tables as the data source.

    Where do you suggest I start debugging to measure the processing time?

    Thanks so much for your help!

  • Martin Dráb Profile Picture
    237,965 Most Valuable Professional on at
    One option is starting by measuring the whole process to see which component is the most problematic. If the theory proves true and the data provider class (FreeTextInvoiceDP) takes a lot of time, look at details there. For example, you may find a particular slow query.
     
    Because slow queries are a common problem, you may actually start with them. You can look at something like Query store to check if there isn't anything obviously wrong. The Trace parser can highlight slow queries too.
     
    But of course, the problem may be caused by something else. We can't know without checking.
  • Mario C Profile Picture
    80 on at

    ok I’ll look into those suggestions and update this thread with the results of the analysis, thanks again Martin.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 451 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 428 Super User 2025 Season 2

#3
BillurSamdancioglu Profile Picture

BillurSamdancioglu 239 Most Valuable Professional

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans