Epicor Function - Set value from a BAQ to a variable

Hi,

I read some posts about invoking a BAQ in an Epicor Function, but I can’t seem to figure out how to set a value from that BAQ to a variable that I create.

There is a ud_Select_c field on the JobOper table. I want to bring in only the JobNum, AssemblySeq, and OprSeq when the Select_c is checked, in order to perform additional processing in my function. I was able to invoke the BAQ in my function but am having trouble retrieving any data from the <return value> dataset.

Here’s what I got so far:
image

image

How do I retrieve data from the return dataset? For example, when I try to assign the JobNum from the BAQ to another variable, I get nothing from the dsBAQResults table. Does anyone know what might be the issue? I suspect I might be missing something important.

image

Thank you in advance!

So your variable dsBAQResults is a System.Data.DataSet type, which is a collection of DataTables. In the case of BAQs, it should contain only 1 table which will be named “Results”. The table will contain a collection of rows and their fields (named exactly as they’re shown in the BAQ Display Fields table).

So if you want to see the JobNum from the first row of the BAQ from the dsBAQResults dataset, it would look like this:

DataRow FirstRow = dsBAQResults.Tables["Results"].Rows[0];

string FirstJobNum = (string)FirstRow["JobHead_JobNum"];

If you’d like to loop through your results:

foreach ( DataRow row in dsBAQResults.Tables["Results"].Rows )
{
    string JobNum = row["JobHead_JobNum"];
}
3 Likes

Thank you, Kevin! I realize I need to convert the variables to their correct data types when looping through my results.

So, I made some updates to the code here:

foreach (DataRow row in dsBAQResults.Tables[“Results”].Rows )
{
string JobNum = Convert.ToString(row[“JobOper_JobNum”]);
int AssemblySeq = Convert.ToInt32(row[“JobOper_AssemblySeq”]);
int OprSeq = Convert.ToInt32(row[“JobOper_OprSeq”]);
}

Let’s say I want to display only the JobNum in a message box from the dsBAQResults table. How do I do that? Alternatively, how can I assign the value from JobNum to another variable outside of dsBAQResults.Tables?

image

To assign it to a variable that can be used outside of the dsBAQResults, all you need to do is declare the variable outside the scope of the Loop and then assign it within the loop.

string DisplayJobNums = string.Empty;

foreach ( DataSet row in dsBAQResults.Tables["Results"].Rows )
{
    string ThisJobNum = (string)row["JobOper_JopNum"];
    DisplayJobNums += $"{ThisJobNum}, ";
}

// result of DisplayJobNums: "JobNum0, JobNum1, JobNum2, JobNum2, "
1 Like

Thank you so much, Kevin.

Another question, can the result of DisplayJobNums be used by other variables inside the function?

Yep. I just created a variable outside the scope for that example, you can use BPM Variables as well.

I apologize if I haven’t been clear about my question.

Once the columns are created and stored in dsBAQResults (in this case, JobNum, AssemblySeq, and OprSeq), how can I use these fields?

For example, if JobNum equals 12345, and I display dsBAQResults.JobNum, I want the message to show 12345. I understand it might not be this straightforward, but I hope you get my point lol :joy:

Do I need to convert the dataset to a table and set tableset.columns equal to dataset.columns?

So the dsBAQResults won’t have a job number, it will have a bunch of rows with job numbers. So what you have is something like this:

Table "Results":

JobNum AssemblySeq OprSeq
12345 0 10
12345 0 20
12345 0 30
23456 0 10
23456 0 20

if you want to display the first JobNum in a message, you can set a BPM level variable (like your “selectJobs”), you would then do something like this

// String variable DisplayJobInfo set in the BPM Variables

DataRow FirstRow = dsBAQResults.Tables["Results"].Rows[0];
string dispJobNum = (string)FirstRow["JobOper_JobNum"];
int dispAsmSeq = (int)FirstRow["JobOper_AssemblySeq"];
int dispJobOpr = (int)FirstRow["JobOper_OperSeq"];

DisplayJobInfo = $"JobNum: {dispJobNum}\nAssembly: {dispAsmSeq}\nOperSeq: {dispJobOpr}";

Then in your message, you can just add the DisplayJobInfo variable, which will be formatted like this:

JobNum: 12345
Assembly: 0
OperSeq: 10
2 Likes

A big THANK YOU, Kevin!! I got it to work. :partying_face: :partying_face:

1 Like

@kve Hi Kevin, I might be missing something here. I am trying to automatically create Labor Transactions on Time Entry based on the jobs selected by the user from a BAQ.

I called this BAQ in my function, but for some reason, it only captures one job instead of all the jobs that are being selected. I think my code is missing some key elements since it seems to only grab one row from the data set.

try
{

    if(dsMyQueryResults.Tables.Count > 0 && dsMyQueryResults.Tables["Results"] != null)
    {
     
      foreach (DataRow row in dsMyQueryResults.Tables["Results"].Rows )
     {
        // variables are defined inside the function designr. 
        iJobNum = Convert.ToString(row["JobOper_JobNum"]);
        iAsmSeq = Convert.ToInt32(row["JobOper_AssemblySeq"]);
        iOperSeq = Convert.ToInt32(row["JobOper_OprSeq"]);
      }
    }
}
catch
{
 
}

Do you know what the issue might be? I can share my function if needed. Thank you in advance.

Hi Eric,

I’m not sure what might be missing, except that it looks like your variables are defined outside of the foreach loop. Because of that, they’ll be replaced after each loop in the foreach, so that the variables would always be the values from the last row only. If you want to do a transaction for every row returned by the query, you’ll need to put the code to do that inside the foreach loop.

Thank you for your quick response, Kevin. This is exactly what I’m seeing: the query only returned the last row. If I define my variables inside the foreach loop in the custom code widget, how can those variables be used outside of that widget?

For example, I don’t see the JobNum variable, which I defined in a custom code widget, when I try to use it to invoke a BO method.
image

Ah I see the problem.

I think these are the steps you need to take:

  1. Set up a separate function taking EmployeeID, JobNum, AssemblySeq, and OprSeq as input parameters. (You can do this in the same library if you’re in Kinetic, it will have to be a different library if you’re in 10.2.X00).

  2. Add your Invoke BO Method bit using those input parameters in the Setup Method Parameters dialog.

  3. Remove your Invoke BO Method from the original function.

  4. Inside the foreach loop on the BAQ results, call the new function using the variables after defining them, like this:

try
{

    if(dsMyQueryResults.Tables.Count > 0 && dsMyQueryResults.Tables["Results"] != null)
    {
     
      foreach (DataRow row in dsMyQueryResults.Tables["Results"].Rows )
     {
        // variables are defined inside the function designr. 
        iJobNum = Convert.ToString(row["JobOper_JobNum"]);
        iAsmSeq = Convert.ToInt32(row["JobOper_AssemblySeq"]);
        iOperSeq = Convert.ToInt32(row["JobOper_OprSeq"]);

        this.ThisLib.InvokeLaborBO( iJobNum, iAsmSeq, iOperSeq ); // Replace ".InvokeLaborBO" with the name of your new function
      }
    }
}
catch
{
 
}
1 Like

We are on Kinetic, so no need for additional library. :partying_face:

I created a separate function and defined EmpNum, JobNum, AssemblySeq, OperSeq, and some other variables as input parameters. However, to invoke the Erp.Labor.DefaultJobNum and Erp.Labor.DefaultOprSeq, I will need to know the JobNum and OprSeq, which are coming from the BAQ. Otherwise, I will receive an error: ‘A valid Job Number/Job Operation Sequence is required’ on the REST API.

Would it be possible to get the results from the BAQ first and then define my variables to tie to the JobNum, AssemblySeq, and OperSeq for BO method calls? Or is there a better way to do this? I want this function to automatically create new labor transactions on Time Entry when users select a Job/Assembly/Operation.

I apologize, as I am learning as I go, and I really appreciate your time helping me out.

Yes that’s exactly what we’ll be doing. So when you create your new function, you can set Input parameters. You will only call that function from inside the loop, and you’ll pass the Job, Assemply, and Operation in from the original Function

Hi Kevin,

Thank you so much for pointing it out! I got it to work. You are absolutely correct; the variables for the BO calls need to be defined inside my loop. This is why I wasn’t getting all the BAQ results.

1 Like

Awesome! Glad to hear you got it working!

1 Like