BPM - Validate string is numeric value

How would you create a BPM condition to verify a numeric value is entered in a nvarchar field? I’m trying to create a BPM to require numeric values only in the Part Rev field or display a warning message.

Please take a look at this thread

How to do a BPM that throws an error if a RegEx variable does not contain (or match) numeric values - Kinetic 202X - Epicor User Help Forum (epiusers.help)

If you’re using a “if this code is valid” condition block:

int n;
return int.TryParse(Revision, out int n))

You can also do a loop

foreach (var character in Revision)	
		return false;

return true;

You can also do regex, but since regex is kind of unreadable. I only use if when my parsing logic gets unwieldy.

1 Like


The important part is to use that isnumeric or tryparse in the same language that will be consuming the value. IE, don’t take C#'s word for it then feed the raw original string to SQL, because C# might (for the sake of example) happily parse “10e2” and SQL might not. The same goes for regex - handwritten regex may or may not accomodate the varieties of numeric expression as the language you’re feeding a string to.

Agree with @jtownsend that sometimes it is easiest to use the brute force method to determine the validity of data…
In the example below, you can even choose which characters are valid:

string MyString = "123^12";
string ValidChars = "123456789-.";

string digitsOnly = new string(MyString.Where(char.IsDigit).ToArray());

bool allDigitsValid = true;
foreach (char digit in digitsOnly)
    if (!ValidChars.Contains(digit))
        allDigitsValid = false;
if (!allDigitsValid)
    {//throw error message

In terms of c#, Int.TryParse() will not accept exponential notation and should work as expected. Decimal.TryParse might do something weird, but only if you also declare the number is a float in the method call.

SQL’s IsNumeric() will absolutely return an exponential function as true, though.

I don’t want to hijack this thread, so if a separate post should be made, mods - please move this, or let me know and I’ll create a new post.

I am also trying to validate that a string is a numeric value in a BPM and keep running into this weird error.

The use case is this: in Case Entry, we don’t want departments being assigned as owners of a case - only users. In our system, user workforce record ids are numeric and department workforce record ids are alphabetic. Case Entry pulls work force records to assign ownership to the case and stores the value in HDCase.CaseOwner.

I created a pre-processing method-directive on Erp.BO.HelpDesk.Update to check if the value of HDCase.CaseOwner in the temp dataset is numeric. If it isn’t, throw an error and terminate.

First, I created a boolean variable titled isNumber, and an int variable titled numVal, then using the Set Argument/Variable widget, set the value of the variables to int.TryParse(dsHDCaseRow.CaseOwner, out numValue).

Next, I added a Condition widget to check the value of isNumber. If it’s not equal to the true expression, raise an exception and terminate.

The problem I’m running into is, if I try to delete a case record with the BPM enabled, I get the error message

The table ds.HDCase has more than one record

Click on the Details tab reveals the following:

Business Layer Exception

The table ds.HDCase has more than one record

Error Detail

Correlation ID: f8782bc5-4ba4-41ed-8bb8-156f2776e3bc
Description: The table ds.HDCase has more than one record
Program: Epicor.Customization.dll
Method: GetSingleRow
Table: ds.HDCase
Field: undefined

When I look at the call to the Update method, there are indeed (2) records being sent in the dataset - one empty except for a RowMod value of D, and one completely empty.

Does anyone have any advice on why this is happening and how to get around it?

That’s common. You’ll have to account for that in your conditions.

First thing, is yes, you’ll have to put a condition block that tests if the RowMod == A (added) or U (updated). D is deleted. Blank is unchanged. You don’t want the BPM to fire on unchanged or deleted rows. If you have old records with wrong owners on them, clean that up before you turn the BPM on.

Second, rather than test for numeric values on update, I’d tie all of the groups to a dummy salesperson, leaving everyone else tied to their person record. Then maybe run a BPM on the CaseOwner drop down that filters out non-person records.

But I always try to tie objects together and build logic off that. That way, I don’t have to rewrite code when management decides to change the numbering scheme.

1 Like

Thanks John. I did have a RowMod condition on the BPM checking for ‘A’ or ‘U’ and I still received the error. It seems like there should only be one record in the dataset being updated but an empty one is being appended.

It’s typical for Update() calls to take a dataset and then return the updated dataset. So, yes, you can have multiple rows, but by the same token, it’s not really going to care about unchanged rows since it expects them. Often, I have to place the Update call within a loop and call it repeatedly for each record. I don’t think that applies here though.

I also recall it throwing the multiple row error if (when adding a row) a field isn’t set correctly, resulting in a key collision.

If I’m on a deadline, I’ll toss the validator on a data directive, since you don’t really have to worry about datasets in those. But I try to come back and do it the right way. Also, as I said above, you should try to filter things before the Update step.

Understood, thanks again John. I may go the DD direction if necessary.

I ended up changing the BPM trigger from Update to OnChangeCaseOwner, then used some RegEx parsing @klincecum suggested in another thread to throw an exception if the CaseOwner isn’t numeric. Appreciate both of you.

1 Like