• Introducing Dark Mode! Switch by clicking on the lightbulb icon next to Search or by clicking on Default style at the bottom left of the page!

dynamic error messages


VIP Member
I've seen error message defined in Data Dictionary that have &1 and &2 which appear to be dynamically populated at runtime. Now I can only assume that they are using printf server side to create these message dynamically, but is there a way to produce this same type of dynamic messages using named event rules in FDA?



Legendary Poster
I can't remember the function name but there is a function or functions that you can call from ER code that does this. They basically take the error code as a parameter and then the text substitution for the other parameter(s). Mind you that these are specific for a given DD error structure like DE0022 so you have to make sure that the error ID you pass implements the same DD error structure as the text substitution error function. One thing you lose with a lot of these functions is CALLMAP support - in other words if you create an NER that throws an error on the Qty field but instead call a function to throw your error the Qty field won't be red.

Here is one we have that will do text substitution for an error that implements DE0022 that DOES have optional CALLMAP support:

 * TYPEDEF for Data Structure
 *    Template Name: Set Error With Text Substitution
 *    Template ID:   D5800005F
 *    Generated:     Mon Nov 21 16:34:30 2005
 *    To make modifications, use the OneWorld Data Structure
 *    Tool to Generate a revised version, and paste from
 *    the clipboard.

#ifndef DATASTRUCTURE_D5800005F
#define DATASTRUCTURE_D5800005F

typedef struct tagDSD5800005F
  JCHAR              szErrorId[11];                       
  JCHAR              szTextSubstitution[41];              
  JCHAR              szCALLMAP[2];                        
  MATH_NUMERIC      mnCALLMAP;                           
  JCHAR              cCALLMAP;                            
  ID                idCALLMAP;                           
  JCHAR              cSetErrOnStringField;                
  JCHAR              cSetErrOnMathNumericField;           
  JCHAR              cSetErrOnCharField;                  
  JCHAR              cSetErrOnIDField;                    
} DSD5800005F, *LPDSD5800005F;

#define IDERRszErrorId_1                          1L
#define IDERRszTextSubstitution_2                 2L
#define IDERRszCALLMAP_3                          3L
#define IDERRmnCALLMAP_4                          4L
#define IDERRcCALLMAP_5                           5L
#define IDERRidCALLMAP_6                          6L
#define IDERRcSetErrOnStringField_7               7L
#define IDERRcSetErrOnMathNumericField_8          8L
#define IDERRcSetErrOnCharField_9                 9L
#define IDERRcSetErrOnIDField_10                  10L


 *  Business Function:  AcmeSetErrorWithTextSubstitute
 *        Description:  AcmeSetErrorWithTextSubstitute
 *         Parameters:
 *           LPBHVRCOM           lpBhvrCom    Business Function Communications
 *           LPVOID              lpVoid       Void Parameter - DO NOT USE!
 *           LPDSD5800005F       lpDS         Parameter Data Structure Pointer  

JDEBFRTN (ID) JDEBFWINAPI AcmeSetErrorWithTextSubstitute (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD5800005F lpDS)  
    *  Variable declarations
	ID idCallMap = 0;

    * Check for NULL pointers
   if ((lpBhvrCom == (LPBHVRCOM) NULL) ||
       (lpVoid    == (LPVOID)    NULL) ||
       (lpDS      == (LPDSD5800005F)	NULL))
     jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, _J("4363"), (LPVOID) NULL);
     return ER_ERROR;

    * Main Processing

	/* set the call map */
	if(lpDS->cSetErrOnStringField == _J('1'))
		idCallMap = IDERRszCALLMAP_3;
	else if(lpDS->cSetErrOnMathNumericField == _J('1'))
		idCallMap = IDERRmnCALLMAP_4;
	else if(lpDS->cSetErrOnCharField == _J('1'))
		idCallMap = IDERRcCALLMAP_5;
	else if(lpDS->cSetErrOnIDField == _J('1'))
		idCallMap = IDERRidCALLMAP_6;

	/* call the error */
		jdeErrorSet(lpBhvrCom, lpVoid, idCallMap, lpDS->szErrorId, (LPVOID)NULL);
		DSDE0022 dsErr = {0};
		jdeStrncpyTerminate(dsErr.szDescription, lpDS->szTextSubstitution, DIM(dsErr.szDescription));
		jdeErrorSet(lpBhvrCom, lpVoid, idCallMap, lpDS->szErrorId, (LPVOID)&dsErr);

   return ER_SUCCESS;


VIP Member
I ended up just returning a dynamic error message in the bsfn and a generic message in dd.

so when calling the bsfn it returns
dtai(error code) useful to check when calling bsfn and setting error on form
errdgop(error desc) different depending on the execution of the bsfn.