Skip to main content

Notifications

Announcements

No record found.

Finance | Project Operations, Human Resources, ...
Answered

Batch job to run report

(1) ShareShare
ReportReport
Posted on by 284
Hello everyone,
 
A user has asked me to build a report that we can send to vendors.  A /scorecard/ if you will.  He wants it to be sent to all vendors every quarter.

So first I created a report from a button that you could run for one vendor, just to make sure it's working.  I put dates as parameters so we could run some stuff from the past to see if it was working right.  After working out all the bugs, the report works great.  I'm using Docentric for the report which is like any other SSRS except is has a DSP class included with the DP, Controller and Contract classes.  I'm also sending the report via email to whomever is marked as the contact in the vendor itself.  Here is a screen shot of how I would run it manually for one vendor
 


So now I want to create a batch class that loops through the vendors and then sends that report.  I can then setup that batch job to recur every 3 months.  I'm getting an error when trying to run it and it's probably because I'm not sure how to set up the email settings.  Can someone please help.
 
Here is my code in the run method of my RunBaseBatch class
 
public void run()    {        VendTable                       vendTable;        Args                            args;        TCI_SupplierScoreCardController controller;        TCI_SupplierScoreCardContract   contract = new TCI_SupplierScoreCardContract();        while select vendTable            where vendTable.TCI_SendSupplierScoreCard == NoYes::Yes        {            args = new Args();            args.record(vendTable);            controller = new TCI_SupplierScoreCardController();            controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));            controller.parmArgs(args);                        //contract = controller.parmReportContract().parmRdlContract();            contract.parmRecId(vendTable.RecId);            contract.parmEndDate(today());                        DatePhysical            newStartDate;            newStartDate = prevMth(today());            newStartDate = prevMth(newStartDate);                    contract.parmStartDate(newStartDate);            SRSPrintDestinationSettings pds = controller.parmReportContract().parmPrintSettings();            pds.printMediumType(SRSPrintMediumType::Email);            controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);            controller.parmShowDialog(false);            controller.startOperation();        }    }
 
  • Verified answer
    Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    I got this working now!  Thanks for the advice Martin.
     
    This is the code from my controller
    protected void prePromptModifyContract()
        {
            TCI_SupplierScoreCardContract      contract = this.parmReportContract().parmRdpContract();
       
            contract.parmRecId(args.record().RecId);
       
            this.parmReportContract().parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
              
            boolean isPreview = false;
      
            //Set the target print destination to screen
            if (isPreview)
            {
                this.parmReportContract().parmPrintSettings().printMediumType(SRSPrintMediumType::Screen);
            }
    
            if (args.menuItemName() != '')
            {
                this.parmShowDialog(!isPreview);
                this.parmLoadFromSysLastValue(!isPreview);
            }  
            
      
        }
    That line about the menu item let's me keep a button that can call this controller and let the user run this report for one vendor and send it to themselves
     
    Here is the run method from my RunBaseBatch class that I run from batch jobs
    public void run()
        {
            VendTable                       vendTable;
            DirPartyLocation                dirPartyLocation;
            LogisticsElectronicAddress      logisticsElectronicAddress;
            LogisticsElectronicAddressRole  logisticsElectronicAddressRole;
            LogisticsLocationRole           logisticsLocationRole;
            Args                            args;
            TCI_SupplierScoreCardController controller;
            TCI_SupplierScoreCardContract   contract;
            str                             email;
            boolean                         first = true;
    
            while select vendTable
                where vendTable.TCI_SendSupplierScoreCard == NoYes::Yes
            {
                while select dirPartyLocation
                    where dirPartyLocation.party == vendTable.Party
                {
                    while select logisticsElectronicAddress
                        where logisticsElectronicAddress.Location == dirPartyLocation.Location
                        && logisticsElectronicAddress.Type == LogisticsElectronicAddressMethodType::Email
                    {
                        while select logisticsElectronicAddressRole
                            where logisticsElectronicAddressRole.ElectronicAddress == logisticsElectronicAddress.RecId
                            join logisticsLocationRole
                            where logisticsLocationRole.RecId == logisticsElectronicAddressRole.LocationRole
                            && logisticsLocationRole.Name == 'PO EMAIL'
                        {
                            if(first)
                            {
                                email = logisticsElectronicAddress.Locator;
                                first = false;
                            }
                            else
                            {
                                email = email + ";" + logisticsElectronicAddress.Locator;
                            }
                        
                        }
                    }
                }
    
                controller = new TCI_SupplierScoreCardController();
    
                args = new Args();
                args.record(vendTable);
    
                controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
                controller.parmArgs(args);
    
                contract = controller.parmReportContract().parmRdpContract();
                contract.parmRecId(vendTable.RecId);
                contract.parmEndDate(today());            
    
                DatePhysical    newStartDate;
                newStartDate = prevMth(today());
                newStartDate = prevMth(newStartDate);
            
                contract.parmStartDate(newStartDate);
    
                // Set the Docentric Email print destination settings.
                SRSPrintDestinationSettings pds = controller.parmReportContract().parmPrintSettings();
                pds.printMediumType(SRSPrintMediumType::Email_DC);
    
                // Set report template
                pds.parmSrsPrintReportSettings_DC().parmTemplateId('TCI_SupplierScoreCard.Report');     // Use '' for @DOCENTRIC_DEFAULT_TEMPLATE@ or use 'SalesPackingSlip.Report' for a specific report template
    
                // Set email recipient(s)
                pds.parmEmailPrintDestSettings_DC().parmEmailTo(email); // In the To, Cc and Bcc fields, placeholders and email tokens can also be specified, e.g. @WORKEREMAIL@ as placeholder or @@ as primary contact email token
                //pds.parmEmailPrintDestSettings_DC().parmEmailCc('cc@docentric.com');
                //pds.parmEmailPrintDestSettings_DC().parmEmailBcc('bcc@docentric.com');
    
                // Set email subject
                pds.parmEmailPrintDestSettings_DC().parmEmailSubject('Test @VendorId@');
    
                // Set email attachment name and format
                pds.parmEmailPrintDestSettings_DC().parmEmailAttachmentName('Test @VendorId@.pdf');
                pds.parmEmailPrintDestSettings_DC().parmEmailAttachmentFileFormat(DocOutputFileFormat::PDF);
                
                controller.parmShowDialog(false);
                controller.startOperation();
            }
        }
    And one other thing I needed to do in the main method of the RunBaseBatch class was comment out the part to check for the prompt
    public static void main(Args args)
        {
            TCI_SupplierScoreCardBatch tci_SupplierScoreCardBatch = new TCI_SupplierScoreCardBatch();
            tci_SupplierScoreCardBatch.parmInBatch(false);
    
            //if (tci_SupplierScoreCardBatch.prompt())
                tci_SupplierScoreCardBatch.runOperation();
        }
    Now everything is working perfectly.  Thanks Martin for all your help as usual!
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    I was hoping to show the dialog if I run it from one button, so perhaps I can put in some code in that controller and check what called it. If it's called from the button, then show dialog otherwise don't.
     
    I will try that and get back to you. 
  • Martin Dráb Profile Picture
    Martin Dráb 230,569 Most Valuable Professional on at
    Batch job to run report
    When you debug your controller, I think you'll find that the value of parmShowDialog() is get from SysLastValue in startOperation(), overwriting what you specified before.
     
    If this controller shouldn't ever display a dialog, you can simply override parmShowDialog() and let it always return false.
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    I have some updates but I'm still not quite there.
    I've updated the code in my batch class
    I had to comment out this part in the Main() so I wouldn't get that error I posted
    public static void main(Args args)
        {
            TCI_SupplierScoreCardBatch tci_SupplierScoreCardBatch = new TCI_SupplierScoreCardBatch();
            tci_SupplierScoreCardBatch.parmInBatch(false);
    
            //if (tci_SupplierScoreCardBatch.prompt())
                tci_SupplierScoreCardBatch.runOperation();
        }
    Then I've updated my run() method to look like this
    public void run()
        {
            VendTable                       vendTable;
            DirPartyLocation                dirPartyLocation;
            LogisticsElectronicAddress      logisticsElectronicAddress;
            LogisticsElectronicAddressRole  logisticsElectronicAddressRole;
            LogisticsLocationRole           logisticsLocationRole;
            Args                            args;
            TCI_SupplierScoreCardController controller;
            TCI_SupplierScoreCardContract   contract;
            str                             email;
            boolean                         first = true;
    
            while select vendTable
                where vendTable.TCI_SendSupplierScoreCard == NoYes::Yes
            {
                while select dirPartyLocation
                    where dirPartyLocation.party == vendTable.Party
                {
                    while select logisticsElectronicAddress
                        where logisticsElectronicAddress.Location == dirPartyLocation.Location
                        && logisticsElectronicAddress.Type == LogisticsElectronicAddressMethodType::Email
                    {
                        while select logisticsElectronicAddressRole
                            where logisticsElectronicAddressRole.ElectronicAddress == logisticsElectronicAddress.RecId
                            join logisticsLocationRole
                            where logisticsLocationRole.RecId == logisticsElectronicAddressRole.LocationRole
                            && logisticsLocationRole.Name == 'PO EMAIL'
                        {
                            if(first)
                            {
                                email = logisticsElectronicAddress.Locator;
                                first = false;
                            }
                            else
                            {
                                email = email + ";" + logisticsElectronicAddress.Locator;
                            }
                        
                        }
                    }
                }
    
                controller = new TCI_SupplierScoreCardController();
    
                args = new Args();
                args.record(vendTable);
    
                controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
                controller.parmArgs(args);
    
                contract = controller.parmReportContract().parmRdpContract();
                contract.parmRecId(vendTable.RecId);
                contract.parmEndDate(today());            
    
                DatePhysical    newStartDate;
                newStartDate = prevMth(today());
                newStartDate = prevMth(newStartDate);
            
                contract.parmStartDate(newStartDate);
    
                // Set the Docentric Email print destination settings.
                SRSPrintDestinationSettings pds = controller.parmReportContract().parmPrintSettings();
                pds.printMediumType(SRSPrintMediumType::Email_DC);
    
                // Set report template
                pds.parmSrsPrintReportSettings_DC().parmTemplateId('TCI_SupplierScoreCard.Report');     // Use '' for @DOCENTRIC_DEFAULT_TEMPLATE@ or use 'SalesPackingSlip.Report' for a specific report template
    
                // Set email recipient(s)
                pds.parmEmailPrintDestSettings_DC().parmEmailTo(email); // In the To, Cc and Bcc fields, placeholders and email tokens can also be specified, e.g. @WORKEREMAIL@ as placeholder or @@ as primary contact email token
                //pds.parmEmailPrintDestSettings_DC().parmEmailCc('cc@docentric.com');
                //pds.parmEmailPrintDestSettings_DC().parmEmailBcc('bcc@docentric.com');
    
                // Set email subject
                pds.parmEmailPrintDestSettings_DC().parmEmailSubject('Test @VendorId@');
    
                // Set email attachment name and format
                pds.parmEmailPrintDestSettings_DC().parmEmailAttachmentName('Test @VendorId@.pdf');
                pds.parmEmailPrintDestSettings_DC().parmEmailAttachmentFileFormat(DocOutputFileFormat::PDF);
                
                controller.parmShowDialog(false);
                controller.startOperation();
            }
    And if I click the button to run this class, it works (sort of).  I get prompted
     
    If I click OK here, it works.  All the emails and the dates are filled out correctly, and right now I have 2 test vendors, so it prompts me again, I click OK again and it works perfectly.

    My only issue now is, I don't want it to prompt.  I want it to run silently so I can setup this as a batch job
    If I go into batch jobs and try to run this class, I get the same error as before
     
    Which I'm thinking is because it's prompting but that won't work in batch.

    Can someone please help me get past this.  I don't understand why it's prompting when I clearly put in the code "controller.parmShowDialog(false);"
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    I created the batch job under batch jobs in Sys Administration but it never hit my breakpoint
    so I created a button to run that class and when I tried to debug, I didn't even hit my code.  I got this message
     
  • Martin Dráb Profile Picture
    Martin Dráb 230,569 Most Valuable Professional on at
    Batch job to run report
    You can use the debugger to see where the code fails.
     
    A problem I see is that you set values of contract object, but never use the contract for anything. You can pass it to controller.parmReportContract().parmRdpContract().
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    I found some new code to try on another post.  My code now looks like this
     
    public void run()
        {
            VendTable                       vendTable;
            Args                            args;
            TCI_SupplierScoreCardController controller = new TCI_SupplierScoreCardController();
            TCI_SupplierScoreCardContract   contract = new TCI_SupplierScoreCardContract();
            SRSPrintDestinationSettings     settings;
    
            while select vendTable
                where vendTable.TCI_SendSupplierScoreCard == NoYes::Yes
            {
                //args = new Args();
                //args.record(vendTable);
    
                controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
                controller.parmShowDialog(false);
                //controller.parmArgs(args);            
    
                //contract = controller.parmReportContract().parmRdlContract();
                contract.parmRecId(vendTable.RecId);
                contract.parmEndDate(today());            
    
                DatePhysical    newStartDate;
                newStartDate = prevMth(today());
                newStartDate = prevMth(newStartDate);
            
                contract.parmStartDate(newStartDate);
    
                //SRSPrintDestinationSettings pds = controller.parmReportContract().parmPrintSettings();
                //pds.printMediumType(SRSPrintMediumType::Email);
    
                //controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);
                
                controller.startOperation();
            }
        }
    But I still get an error.  I created a batch job and pointed it to this class.  I didn't set this up via a button or anything
    When I try to run it it give me an error saying
    If someone could point me in the right direction to accomplish what I want, that would be appreciated.  I was thinking about keeping the button that I have now, separate from a batch job that runs quarterly.  That way if someone wants to run the report for one vendor, they can use the button.  I just want a class that runs quarterly, loops through the vendors, fills in the parameters of the contract class and calls the report.....
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    So instead of me posting my error, can we start with you telling me what is the best way for me to run this?  Here is my current controller, in case you need it
     
    class TCI_SupplierScoreCardController extends SrsReportRunController
    {
        public static void main(Args _args)
        {
            SrsReportRunController  controller = new TCI_SupplierScoreCardController();
            controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
            controller.parmArgs(_args);
            controller.startOperation();
        }
    
        protected void prePromptModifyContract()
        {
            TCI_SupplierScoreCardContract      contract = this.parmReportContract().parmRdpContract();
       
            contract.parmRecId(args.record().RecId);
       
            this.parmReportContract().parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
              
            boolean isPreview = false;
      
            //Set the target print destination to screen
            if (isPreview)
            {
                this.parmReportContract().parmPrintSettings().printMediumType(SRSPrintMediumType::Screen);
            }
      
            this.parmShowDialog(!isPreview);
            this.parmLoadFromSysLastValue(!isPreview);
      
        }
    
    }
     
  • Andrew Huisman Profile Picture
    Andrew Huisman 284 on at
    Batch job to run report
    Oh for sure Martin, I knew you would call me out on the error message.  I thought there would be something obvious standing out in my code, or someone would tell me how to do the emailing part so I could try that.

    I also realized I could run the report in batch for the one vendor, I just wasn't sure how to run that same report for all vendors.  I would prefer to learn the "right" way, so what would you suggest?  Where do I start?

    Here is the code in a more readable format (in case anyone still wants to look at it)
     
    public void run()
        {
            VendTable                       vendTable;
            Args                            args;
            TCI_SupplierScoreCardController controller;
            TCI_SupplierScoreCardContract   contract = new TCI_SupplierScoreCardContract();
    
            while select vendTable
                where vendTable.TCI_SendSupplierScoreCard == NoYes::Yes
            {
                args = new Args();
                args.record(vendTable);
    
                controller = new TCI_SupplierScoreCardController();
                controller.parmReportName(ssrsReportStr(TCI_SupplierScoreCard, Report));
                controller.parmArgs(args);            
    
                //contract = controller.parmReportContract().parmRdlContract();
                contract.parmRecId(vendTable.RecId);
                contract.parmEndDate(today());            
    
                DatePhysical            newStartDate;
                newStartDate = prevMth(today());
                newStartDate = prevMth(newStartDate);
            
                contract.parmStartDate(newStartDate);
    
                SRSPrintDestinationSettings pds = controller.parmReportContract().parmPrintSettings();
                pds.printMediumType(SRSPrintMediumType::Email);
    
                controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);
                controller.parmShowDialog(false);
                controller.startOperation();
            }
        }
     
  • Martin Dráb Profile Picture
    Martin Dráb 230,569 Most Valuable Professional on at
    Batch job to run report
    Saying that you're getting an error isn't very detailed. Please tell us what the error message says and where the exception is thrown.
     
    By the way, the report controller class already supports batch processing. Maybe you could do the work there rather than creating a separate class running the controller in a loop.

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

Congratulations 2024 Spotlight Honorees

Kudos to all of our 2024 community stars! 🎉

Meet the Top 10 leaders for December

Congratulations to our December super stars! 🥳

Start Your Super User Journey Pt 2

Join the ranks of our community heros! 🦹

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,885 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,569 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Product updates

Dynamics 365 release plans