Wednesday, April 8, 2020

How-to send PDF document to a printer from X++

In AX 2012 it could be done with 2 lines of X++ code:
1
2
#WinAPI
WinApi::shellExecute(fileName,'', fileFolder, #ShellExePrint);
Now it’s not that easy. Files are in Azure BLOB storage instead of a folder, printers are in a local network that is not accessible from the cloud and WinApi is deprecated. To print standard reports Document Routing Agent should be installed. We need it to send PDF directly from the system as well.
Let’s say we want to print PDF file saved in document attachments (DocuRef). First, we need to check if a printer selected by a user is active and get printer details:
1
2
3
4
5
SrsReportPrinterContract activePrinterContract = SrsReportRunUtil::getActivePrinter(printerName);
if (!activePrinterContract.parmPrinterName())
{
    return;
}
printerName value should come from somewhere, for example a field on a form. In this case we can use SrsReportRunUtil::lookupPrinters() method to add a lookup with all available printers:
1
2
3
4
public static void lookupPrinters(FormStringControl _ctrl)
{
    SrsReportRunUtil::lookupPrinters(_ctrl);
}
Then we need to create print destination settings:
1
2
3
4
5
6
7
8
9
10
11
SRSPrintDestinationSettings srsPrintDestinationSettings = new SRSPrintDestinationSettings();
srsPrintDestinationSettings.printMediumType(SRSPrintMediumType::Printer);
srsPrintDestinationSettings.fileFormat(SRSReportFileFormat::PDF);
srsPrintDestinationSettings.printerName(activePrinterContract.parmPrinterName());
srsPrintDestinationSettings.printerWhere(activePrinterContract.parmPrinterPath());
srsPrintDestinationSettings.numberOfCopies(1);
srsPrintDestinationSettings.collate(false);
srsPrintDestinationSettings.printOnBothSides(SRSReportDuplexPrintingSetting::None);
srsPrintDestinationSettings.printAllPages(true);
srsPrintDestinationSettings.fromPage(0);
srsPrintDestinationSettings.toPage(0);
srsPrintDestinationSettings.printerWhere() is important bit here. This parameter accepts path to a printer. It’s possible to install multiple DRA on different servers and path for DRA installed on a print server could be different to path for DRA installed on any other server, so watch for this.
To send document we need to read file into a memory stream:
1
2
container fileCon = DocumentManagement::getAttachmentAsContainer(_docuRef);
var stream = Binary::constructFromContainer(fileCon).getMemoryStream();
And create new DocumentContract:
1
2
3
4
5
6
7
DocumentContract documentContract = DocumentContractFactory::Instance.Create(DocumentContractType::Pdf);
 
documentContract.Name = _docuRef.Name;
documentContract.Contents =  stream.ToArray();
documentContract.TargetType = TargetType::Printer;
documentContract.Settings = srsPrintDestinationSettings.printerPageSettings();
documentContract.ActivityID = newGuid();
If you send multiple documents ActivityID should be initialized for each document. Don’t forget to add a reference to Microsoft.Dynamics.AX.Framework.DocumentContract:
1
using Microsoft.Dynamics.AX.Framework.DocumentContract;
And finally send the contract to DRA:
1
SrsReportRunPrinter::sendDocumentContractToDocumentRouter(documentContract);
Whole method:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static void sendToPrinter(DocuRef _docuRef, str _printerName)
{
    SrsReportPrinterContract activePrinterContract = SrsReportRunUtil::getActivePrinter(_printerName);
    if (!activePrinterContract.parmPrinterName())
    {
        return;
    }
 
    SRSPrintDestinationSettings srsPrintDestinationSettings = new SRSPrintDestinationSettings();
    srsPrintDestinationSettings.printMediumType(SRSPrintMediumType::Printer);
    srsPrintDestinationSettings.fileFormat(SRSReportFileFormat::PDF);
    srsPrintDestinationSettings.printerName(activePrinterContract.parmPrinterName());
    srsPrintDestinationSettings.printerWhere(activePrinterContract.parmPrinterPath());
    srsPrintDestinationSettings.numberOfCopies(1);
    srsPrintDestinationSettings.collate(false);
    srsPrintDestinationSettings.printOnBothSides(SRSReportDuplexPrintingSetting::None);
    srsPrintDestinationSettings.printAllPages(true);
    srsPrintDestinationSettings.fromPage(0);
    srsPrintDestinationSettings.toPage(0);
 
    container fileCon = DocumentManagement::getAttachmentAsContainer(_docuRef);
    if (fileCon)
    {
        var stream = Binary::constructFromContainer(fileCon).getMemoryStream();
        if (stream)
        {
            DocumentContract documentContract = DocumentContractFactory::Instance.Create(DocumentContractType::Pdf);
            documentContract.Name = _docuRef.Name;
            documentContract.Contents =  stream.ToArray();
            documentContract.TargetType = TargetType::Printer;
            documentContract.Settings = srsPrintDestinationSettings.printerPageSettings();
            documentContract.ActivityID = newGuid();
SrsReportRunPrinter::sendDocumentContractToDocumentRouter(documentContract);
        }
    }
}
If you want to check documents printed or see if there are any in a queue you can go to Common -> Inquiries -> Document routing status
DRA status

No comments:

Post a Comment