microsoft-dynamicsdynamics-business-centraldynamics-al

How Do I Get a Customer's Custom Report Layout ID from their Document Layouts in Business Central?


I am writing a Business Central extension that adds a button to the Sales Order List page, which saves a PDF copy of a sales order confirmation with the file name format "Sales Order [Order No.].pdf".

Some customers may have custom report layouts defined in their Customer Card > Customer > Document Layouts, which should result in a different layout being used than the one specified in Report Layout Selection.

However, the methods I have found to save reports require a report ID (Report.SaveAs, Report.Execute), and I am not sure how to retrieve the custom report layout IDs from the customer document layouts. There isn't a table for document layouts as far as I know.

Below is the code I have so far, which works as intended barring the custom report layout issue.

pageextension 50100 SalesOrderExt extends "Sales Order List"
{
    actions
    {
        addafter("Print Confirmation")
        {
            action("Save Confirmation as PDF")
            {
                Caption = 'Save Confirmation As PDF';
                ApplicationArea = All;
                Image = ExportFile;
                Promoted = true;
                PromotedCategory = Category8;
                PromotedIsBig = true;
                ToolTip = 'Save the order confirmation as a PDF';

                trigger OnAction()
                var
                    SalesHeader: Record "Sales Header";
                    TempBlob: Codeunit "Temp Blob";
                    FileManagement: Codeunit "File Management";
                    RecRef: RecordRef;
                    OStream: OutStream;
                    XmlParameters: Text;
                begin
                    XmlParameters := '<?xml version="1.0" standalone="yes"?>' +
                                    '<ReportParameters name="Sales Order" id="' + System.Format(Report::"Sales Order") + '">' +
                                        '<Options>' +
                                            '<Field name="NoCopies">0</Field>' +
                                            '<Field name="PrintCompany">false</Field>' +
                                            '<Field name="ArchiveDocument">false</Field>' +
                                            '<Field name="LogInteraction">false</Field>' +
                                            '<Field name="DisplayAssemblyInformation">false</Field>' +
                                        '</Options>' +
                                        '<DataItems>' +
                                            '<DataItem name="Sales Header">VERSION(1) SORTING(Field1,Field3) WHERE(Field3=1(' + Rec."No." + '))</DataItem>' +
                                            '<DataItem name="Sales Line">VERSION(1) SORTING(Field1,Field3,Field4)</DataItem>' +
                                            '<DataItem name="SalesLineComments">VERSION(1) SORTING(Field1,Field2,Field7,Field3)</DataItem>' +
                                            '<DataItem name="Sales Comment Line">VERSION(1) SORTING(Field1,Field2,Field7,Field3)</DataItem>' +
                                            '<DataItem name="CopyLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                            '<DataItem name="PageLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                            '<DataItem name="SalesLine">VERSION(1) SORTING(Field1)</DataItem>' +
                                            '<DataItem name="AsmLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                        '</DataItems>' +
                                    '</ReportParameters>';
                    SalesHeader.Reset();
                    SalesHeader.SetRange("Document Type", Rec."Document Type");
                    SalesHeader.SetRange("No.", Rec."No.");
                    SalesHeader.FindFirst();
                    Clear(OStream);
                    CurrPage.SetSelectionFilter(SalesHeader);
                    RecRef.GetTable(SalesHeader);
                    TempBlob.CreateOutStream(OStream, TextEncoding::UTF8);
                    Report.SaveAs(Report::"Sales Order", XmlParameters, ReportFormat::Pdf, OStream, RecRef);
                    FileManagement.BLOBExport(TempBlob, 'Sales Order ' + Rec."No." + '.pdf', true);
                end;
            }
        }
    }
}

Solution

  • It turns out the references are located in the Custom Report Selection table. The "Source No." field that is hidden from the UI in Business Central.

    Here is the working code below:

    pageextension 50100 SalesOrderExt extends "Sales Order List"
    {
        actions
        {
            addafter("Print Confirmation")
            {
                action("Save as PDF")
                {
                    Caption = 'Save As PDF';
                    ApplicationArea = All;
                    Image = ExportFile;
                    Promoted = true;
                    PromotedCategory = Category8;
                    PromotedIsBig = true;
                    ToolTip = 'Save the order as a PDF';
    
                    trigger OnAction()
                    var
                        SalesHeader: Record "Sales Header";
                        CustomReportSelection: Record "Custom Report Selection";
                        ReportLayoutSelection: Record "Report Layout Selection";
                        TempBlob: Codeunit "Temp Blob";
                        FileManagement: Codeunit "File Management";
                        RecRef: RecordRef;
                        OStream: OutStream;
                        ReportType: Integer;
                        XmlParameters: Text;
                    begin
                        ReportType := Report::"Sales Order";
                        CustomReportSelection.Reset();
                        CustomReportSelection.SetRange("Report ID", ReportType);
                        CustomReportSelection.SetRange("Source No.", Rec."Bill-to Customer No.");
                        if not CustomReportSelection.IsEmpty then begin
                            CustomReportSelection.FindFirst();
                            ReportLayoutSelection.SetTempLayoutSelected(System.Format(CustomReportSelection."Custom Report Layout Code"))
                        end;
                        SalesHeader.Reset();
                        SalesHeader.SetRange("Document Type", Rec."Document Type");
                        SalesHeader.SetRange("No.", Rec."No.");
                        XmlParameters := '<?xml version="1.0" standalone="yes"?>' +
                                        '<ReportParameters name="Sales Order" id="' + System.Format(ReportType) + '">' +
                                            '<Options>' +
                                                '<Field name="NoCopies">0</Field>' +
                                                '<Field name="PrintCompany">false</Field>' +
                                                '<Field name="ArchiveDocument">false</Field>' +
                                                '<Field name="LogInteraction">false</Field>' +
                                                '<Field name="DisplayAssemblyInformation">false</Field>' +
                                            '</Options>' +
                                            '<DataItems>' +
                                                '<DataItem name="Sales Header">VERSION(1) SORTING(Field1,Field3) WHERE(Field3=1(' + Rec."No." + '),Field4=1(' + Rec."Bill-to Customer No." + '))</DataItem>' +
                                                '<DataItem name="Sales Line">VERSION(1) SORTING(Field1,Field3,Field4)</DataItem>' +
                                                '<DataItem name="SalesLineComments">VERSION(1) SORTING(Field1,Field2,Field7,Field3)</DataItem>' +
                                                '<DataItem name="Sales Comment Line">VERSION(1) SORTING(Field1,Field2,Field7,Field3)</DataItem>' +
                                                '<DataItem name="CopyLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                                '<DataItem name="PageLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                                '<DataItem name="SalesLine">VERSION(1) SORTING(Field1)</DataItem>' +
                                                '<DataItem name="AsmLoop">VERSION(1) SORTING(Field1)</DataItem>' +
                                            '</DataItems>' +
                                        '</ReportParameters>';
                        Clear(OStream);
                        CurrPage.SetSelectionFilter(SalesHeader);
                        RecRef.GetTable(SalesHeader);
                        TempBlob.CreateOutStream(OStream, TextEncoding::UTF8);
                        Report.SaveAs(ReportType, XmlParameters, ReportFormat::Pdf, OStream, RecRef);
                        FileManagement.BLOBExport(TempBlob, CopyStr(CurrPage.ObjectId(true), 6) + ' ' + Rec."No." + '.pdf', true);
                        ReportLayoutSelection.SetTempLayoutSelected('');
                    end;
                }
            }
        }
    }