BAQ Report export to PDF using Epicor Function

Hello,

I am on Epicor Kinetic 2024.1.12 and I am trying to develop an Epicor function that runs a BAQ report and downloads the output to a folder. I am able to do that successfully on BAQ reports that don’t have any Filters or Options. Could someone point me in the right direction to help me pass values to the Option fields?

Here is what I am doing in that function -

Request Parameters

  1. ReportID (System.String)
  2. BAQID (System.String)
  3. ReportStyleNum (System.String)

Response Parameters
BAQReportParamOutput (Ice.Tablesets.BAQReportTableset)

Variables
CurrentGUID (Type - Guid)

Function Design

  1. Invoke BO method (Ice.BAQReport.GetNewParametersForReportId) and pass the request parameter ReportID. The output is stored in the response parameter BAQReportParamOutput

  2. Set argument/variable CurrentGUID = System.Guid.NewGuid()

  3. Assign values to the following properties of the added row in the BAQReportParamOutput.BAQReportParam table - BAQID, ReportID, BAQRptID, AutoAction, WorkstationID, AgentSchedNum, AgentTaskNum, SSRSRenderFormat, TaskNote (set to CurrentGUID)

  4. Invoke BO method (Ice.BAQReport.RunDirect) by passing the modified dataset BAQReportParamOutput from step 3

  5. Get the SysTaskNum from the SysTask table where TaskNote = CurrentGUID and use it to get the SysRowID of the corresponding record from the SysRptLst table

  6. Invoke BO Method (Ice.ReportMonitor.GetReportBytes) by passing the SysRowID obtained in step 5. This will return a byte array of the generated PDF

  7. Invoke BO method (Ice.FileTransfer.UploadFile) by passing the byte array from step 6 to generate and export the PDF to the specified folder. In my case, I am using ‘Epicor.ServiceModel.Utilities.SpecialFolder.UserData’

The report that I am trying to make this work with has an Option field ‘Option01’. I tried assigning the value to BAQReportParamOutput.BAQReportParam.Option01, and also passed the xml to BAQReportParamOutput.BAQReportParam.Filter1 that I retrieved from Epicor’s trace log after manually running that BAQ report.

I am not sure what is missing in this design, but Epicor simply runs the BAQ report by ignoring the Option01 value and runs the whole BAQ instead. I would appreciate it if someone could point me in the right direction.

Thank you!

1 Like

Here’s a custom code one I have working that generates a BAQ report that is formatted for Serial Number labels. The filter1 field xml is kind of critical. You need that XML and you need the Option1 value in it. If you’re trying to make it dynamic to do different BAQ Reports, you’ll probably have to do some editing of the filter1 parameter variable.

Func<string, byte[]> GetBAQReport = SerialNo => {

    byte[] reportPDF = null;

    CallService<BAQReportSvcContract>(svc => {

        string taskNote = Guid.NewGuid().ToString(); 
        
        string filter1 = $"<DynamicReportDataSet xmlns=\"http://www.epicor.com/Ice/300/BO/DynamicReport/DynamicReport\"><BAQReport>      <Company />      <BAQRptID>LabelSubAssmSN</BAQRptID>      <Description>Subassembly SN Label</Description>      <ReportTitle />      <FormTitle>SN Label</FormTitle>      <ExportID>SubSNLabel</ExportID>      <SystemFlag>false</SystemFlag>      <Completed>false</Completed>      <GlobalReport>false</GlobalReport>   <IsCrystalReport>false</IsCrystalReport>   <ReportID>LabelSubAssmSN</ReportID>   <CrystalReportName />   <CGCCode />   <SSRSReportName>LabelSubAssmSN.rdl</SSRSReportName>   <SysRevID>42651512</SysRevID>   <SysRowID>e2ba3716-c190-436c-a922-b9bbd9be41f6</SysRowID>   <TempRowID />   <BitFlag>0</BitFlag>   <RowMod />  </BAQReport>  <BAQRptOptionFld>   <Company />   <BAQRptID>LabelSubAssmSN</BAQRptID>   <DataTableID>UD100A</DataTableID>   <FieldName>Number01</FieldName>   <CompOp>&gt;=</CompOp>   <Seq>1</Seq>   <DefaultValue />   <FieldLabel>Number01</FieldLabel>   <DisplayName>UD100A_Number01</DisplayName>   <FieldFormat>&gt;&gt;&gt;9999</FieldFormat>   <EpiGuid />   <IsVisible>false</IsVisible>   <DataType>decimal</DataType>   <SystemFlag>false</SystemFlag>   <DispOrder>0</DispOrder>   <SysRevID>42735834</SysRevID>   <SysRowID>bdae0327-0e37-4a33-8576-acd912ea6fee</SysRowID>   <FieldValue>{SerialNo}</FieldValue>   <TempRowID>Field1</TempRowID>   <BitFlag>0</BitFlag>   <RowMod />  </BAQRptOptionFld>  </DynamicReportDataSet>";
        
        var baqRptTS = svc.GetNewParameters();
        var paramRow = baqRptTS.BAQReportParam.First();
        
        paramRow.BAQID = "SubSNLabel";
        paramRow.BAQRptID = "LabelSubAssmSN";
        paramRow.Option01 = SerialNo;
        paramRow.AutoAction = "SSRSGENERATE";
        paramRow.ReportID = "LabelSubAssmSN";
        paramRow.ReportTitle = "SN Label";
        paramRow.ReportStyleNum = 1;
        paramRow.AgentID = "SystemTaskAgent";
        paramRow.TaskNote = taskNote;
        paramRow.Filter1 = filter1;
        
        svc.RunDirect( baqRptTS );
        
        reportPDF = Db.SysRptLst.Join( Db.SysTask,
                                    x => new { x.Company, x.SysTaskNum },
                                    y => new { y.Company, y.SysTaskNum },
                                    (x,y) => new { sr = x, st = y } )
                                .Where( z => z.st.TaskNote == taskNote )
                                .Select( z => z.sr.RptData )
                                .FirstOrDefault();
                                                    
    });
    
    return reportPDF; 
};

var rptBytes = GetBAQReport( Option1Int.ToString() );

outFileName = @"\\AppServer\EpicorData\Companies\COMPANY\Temp\FileName.pdf";

System.IO.File.WriteAllBytes( outFileName, rptBytes );

As you can see, that string for filter1 has the ReportID, Report Description, BAQID, and others built in. You can see near the end where I added the {SerialNo} variable to the element in the XML string. The Guid and SysRevID don’t seem to be affected by being hardcoded.

1 Like

Thanks a lot, Kevin! That approach worked.

I was converting the DynamicReportDataset output to System.Data.DataSet using Ice.DatasetAdapter.ConvertToGenericDataset() and then using the WriteXml() method to get the xml for the ‘Filter1’ field. Because of that, the root element I got was ‘NewDataSet’.

When I replaced my root element with the root element in your code, the BAQ report filtered the data and provided the expected output. Thank you again for your help.

1 Like