Tuesday, February 22, 2011

Save a Microsoft Dynamics AX 2009 report to a PDF file (First Part)

The following code saves an Axapta report to a PDF file. This is the first article of 3. The next article will show how to save the file into a network share and pass a Sales Order dynamically, and the last part will be about attaching the PDF to an Outlook instance and create a dynamic subject. So, the titles of the three articles will be the same foe exception of the text in parenthesis.

In my case, I'm having a lot of problems saving the file to a network file and then to attach it to Outlook. The code below saves the report to a local palce in your computer.

static void Job10(Args _args)
{
   custConfirmJour     custInvoiceJour;
  SalesFormLetter     salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation,  false);
   PrintJobSettings    printJobSettings = new PrintJobSettings();
   Args                args = new Args();
   boolean             prompt = false;
   boolean             printIt = true;
   ;

    printJobSettings.setTarget(PrintMedium::File);
    printJobSettings.format(PrintFormat::PDF);
    printJobSettings.fileName(@'c:\temp\myfile2.pdf');
  
   salesFormLetter.updatePrinterSettingsFormLetter(printJobSettings.packPrintJobSettings());

   select firstOnly custInvoiceJour
       where custInvoiceJour.salesid == '18-062467';

   args.record(custInvoiceJour);
   args.caller(salesFormLetter);

   new MenuFunction(menuitemoutputstr(SalesConfirmation), MenuItemType::Output).run(args);

}

15 comments:

  1. Hi Bro,

    The code is not saving file for me. instead it is printing report on screen

    ReplyDelete
  2. Hi Sanjeev, are you using the exact same code I posted? I just tried it on my end and it worked as expected.

    Just make sure to set the PrintMedium to File amd the PrintFormat to PDF. Also, make sure that your menu item is pointing to the right class.

    Can you send me the exact code you are using?

    ReplyDelete
  3. How can I save my private report, this one made by me. Code is fine but when I try with my report it doesn't work.

    ReplyDelete
  4. Ran the exact code but it is still printing on screen, using AX 2012.

    ReplyDelete
  5. I just ran the same code in AX 2012 too and it does not save the PDF. It does in AX 2009 though. I need to see what's going on when I have som time to si down and check it. Really busy these days.

    ReplyDelete
  6. Hi All,

    Using AX2009 I've got the same problem: File is not saved. In my case I'm calling another report and I can't pass the printJobSettings like this.

    In stead I use this code:

    Args args = new Args();
    PrintJobSettings pjs = new PrintJobSettings();
    SysReportRun reportRun;
    filename mFile;
    ;


    mFile = "MyFile.pdf";
    winapi::deleteFile(mFile);

    pjs.fileName(mFile);
    pjs.format(PrintFormat::PDF);
    pjs.setTarget(PrintMedium::File);
    pjs.preferredFileFormat(PrintFormat::PDF);

    //Set a preferred printer so the pdf looks normal when the default of the user is
    //a strange printer (like a dot matrix label printer)
    pjs.deviceName(ESR_Parameters::find().PrinterEmulationPDF);

    args.name(reportstr(ESR_Main));
    args.record(ESR_Main::find(mTaskId));
    reportRun = classFactory.reportRunClass(args);

    reportRun.printJobSettings(pjs.packPrintJobSettings());
    reportRun.query().interactive(false);
    reportRun.report().interactive(false);
    reportRun.init();
    reportRun.run();

    Works great, for one thing..... The file is being kept in use.... As long as Ax is open I cannot delete the created PDF because the file is still in use.

    Besides that, this should work in AX2009. If someone has an answer on why AX keeps the file locked.... Please let me know.

    Cheers,
    Gerard

    ReplyDelete
    Replies
    1. Hi,

      Thanks for sharing your code. I was playing with this in my AX 2009 virtual box this morning and I'm able to save the file. I'm not sure what's different in your machine.

      Regrading your question, windows will create a reference on a temp location when AX creates the PDF file, therefore AX will ock the file until it is saved.

      Thanks!

      Delete
  7. Stupid typo in the code :o/ Code works on my AX system. At least: It does for the salesFormLetter.

    Because I'm stuck with AX keeping the file locked with the code I provided I think I will write some additional code to call my report in the same structure as the salesFormLetter_Invoice.

    I found something else however: If I execute the code in a job it works. I can immediatly delete the file. So probably some kind of permission problem. Alhough changing the class from client to server doesn't change anything. Investigate this a bit more next week (long weekend ahead :o)) and will let you know.

    Cheers,
    Gerard

    ReplyDelete
    Replies
    1. That is interesting. Please do share if you find an answer : )

      Thanks for sharing!

      Delete
  8. Well... I found it... The above code I've provided is correct and works like a charm.

    After creating the PDF I attach it (in X++) to an email and send that e-mail. The file was being locked by the E-mail process and not the create PDF process... I forgot the mail.dispose().....

    Cheers !
    Gerard

    ReplyDelete
    Replies
    1. Gerard,

      Thanks for double checking and getting us the answer to this issue.

      The best to you man!

      Delete
  9. Hi Guys,
    From past few days i am trying to send invoice directly to customers via email. I am using AX 2012 and when i goto invoices (Accounts receivable > Common > Open all invoice) on the invoice tab we have an option of sending invoice as email to customers do any one know how does it work.

    or

    Do we have to write in any extra code to get this thing done.

    Guys please help

    ReplyDelete
  10. Hi Everyone

    i want to save PurchRFQSend report in PDF with the help of below code but no resault can someone correct me what i am doing wrong?

    static void SavePurchRFQSendToPDF(Args _args)
    {
    ReportName rptName = reportstr(PurchRFQSend);
    ReportRun rptRun ;
    Args rptArgs = New Args(rptName);
    PrintJobSettings printSetting = New PrintJobSettings();
    FileName fileName;
    PurchRFQCaseId rfqCaseId;
    TransDate transDate;
    str path = "c:\\RFQ_send",
    msg;
    boolean folderexists,fileExists;
    Args args = new Args();

    VendRFQJour vendRFQJour;
    PurchRFQVendLink vendRFQLink;

    // PurchRFQFormLetterReport PurchRFQFormLetterReport = PurchRFQFormLetterReport::construct(PurchRFQUpdateType::Accepted);
    ;
    rfqCaseId = '00000032_250';

    select firstonly vendRFQJour
    where vendRFQJour.RFQCaseId == '00000032_250';


    folderExists = WinAPI::folderExists(path);
    if(!folderExists)
    winAPI::createDirectoryPath(path);
    else
    {
    fileExists = winAPI::fileExists(path +"\\"+fileName+".pdf");
    if(fileExists)
    WinAPI::deleteFile(fileName);
    printSetting.fileName(path +"\\"+fileName+".pdf");
    printSetting.warnIfFileExists(true);
    fileName = rfqCaseId +" - " + Date2str(transDate,123,2,1,2,1,4);
    printsetting.setTarget(PrintMedium::File);
    printsetting.preferredTarget(PrintMedium::File);
    printSetting.suppressScalingMessage(true);
    printSetting.format(PrintFormat::PDF_EMBED_FONTS);
    printSetting.preferredFileFormat(PrintFormat::PDF_EMBED_FONTS);

    args.record(VendRFQJour);
    // args.caller('VendRFQJournal');

    // rptArgs.name(rptName);
    // rptRun = New ReportRun(rptArgs);
    rptRun.unpackPrintJobSettings(printsetting.packPrinterSettings());
    printSetting.outputToClient(false);
    rptRun.unpackPrintJobSettings(printsetting.packPrintJobSettings());
    rptRun.report().interactive(false);
    rptRun.query().interactive(false);
    new MenuFunction(menuItemOutputStr(PurchRFQOriginal),menuItemType::Output).run(args);
    // rptRun.init();
    // rptRun.run();
    }
    }

    ReplyDelete
    Replies
    1. i tried below code it also did'nt work


      static void SavePurchRFQSendToPDF_new01(Args _args)
      {
      VendRFQJour vendRFQJour;
      PurchRFQId rfqId;
      ReportRun reportRun;
      RecordSortedList List = new RecordSortedList(tablenum(VendRFQJour));
      ;
      rfqId ='00000022_248';
      vendRFQJour = VendRFQJour::find(rfqId,false);
      list.ins(VendRFQJour);
      reportRun = new reportRun(New Args(ReportStr(PurchRFQSend)));
      reportRun.args().caller(null);
      ReportRun.args().parmEnumType(EnumNum(PrintCopyOriginal));
      reportRun.args().parmEnum(1);
      reportRun.args().object(List);
      reportRun.args().name("KeepSeettings");
      reportRun.printJobSettings().setTarget(PrintMedium::File);
      reportRun.printJobSettings().format(PrintFormat::PDF);
      reportRun.printJobSettings().fileName("C:\\RFQ_send\\testRFQ.pdf");
      reportRun.run();
      }

      Delete
  11. Hi,
    you can try this code its working perfectly

    ReportRun reportRun;
    RecordSortedList list = new RecordSortedList(55);

    ;

    reportRun = new ReportRun(new Args(ReportStr(TestReport)));

    reportRun.args().caller(null);

    reportRun.args().parmEnum(1);

    reportRun.args().parmEnumType(920);

    reportRun.args().object(List);

    reportRun.args().name("KeepSeetting");

    reportRun.printJobSettings().setTarget(PrintMedium::File);

    reportRun.printJobSettings().format(PrintFormat::PDF);

    reportRun.printJobSettings().fileName(@"\\AOSname\C$\Temp\Test.pdf");

    reportRun.prompt();

    reportRun.run();

    ReplyDelete

Thank you for your thoughts. Your comment will appear in my blog shortly after review.

Have a great day!