return RecordValid("ArticleMain")A typical validation record for table ArticleMain might look like this:
Table structure - table Validation: Fields: table C(30) && Table, or in general, set of rules Order I && Allows to specify an order for evaluating rules. Especially important for variables. Rule M && The actual rule, using VFP syntax - e.g. NOT EMPTY(ClientCode) Spanish M && The corresponding error message, if the rule is violated varname M && Allows evaluation of variables comments M && Comments used by the programmer only Warning L && I think this field is now obsolete Level C(1) && Empty if rule is strict; V for a variable; I to ignore rule without having to erase it; W for warning only Indices: Table on table Order on order Deleted on deleted() Rule on left(rule, 30) Spanish on left(Spanish, 30) MainOrder on table+IIF(level="V","0","1")+BINTOC(order) It might be better to delete the index on deleted(). I had the following function in database stored procedures. ********************************************************************** FUNCTION RecordValid(tcTableName, llEvaluateAllRules) * Record validation. * Meant to be invoked from form.valid(tablename). * Can also be invoked from other places, for instance, triggers. tcTableName = lower(tcTableName) llEvaluateAllRules = .T. && Override second parameter. * save and change settings local lnOldAlias, lcOldExact, lcExpression lnOldAlias = select() lcOldExact = set("exact") set exact off * open validation table if used("validation") select validation else select 0 use validation again endif set order to "mainorder" * evaluate all errors defined in rules table local lcErrorText, llError, lcVarName lcErrorText = "" tcTableName = padr(tcTableName, len(Table)) seek tcTableName scan while table = tcTableName select (lnOldAlias) lcExpression = strtran(Validation.Rule, chr(13) + chr(10), space(1)) do case case Validation.Level = "V" && Variable, que se debe evaluar lcVarName = alltrim(Validation.VarName) local &lcVarName &lcVarName = evaluate(lcExpression) case Validation.Level # "I" && Evaluar la regla de validación. Omitir el caso "Ignorar". if not evaluate(lcExpression) lcErrorText = lcErrorText + iif(Validation.Level = "W", "Advertencia: ", "Error: ") + Validation.Spanish if not Validation.Level = "W" llError = .T. endif if llEvaluateAllRules lcErrorText = lcErrorText + chr(13) else exit endif endif endcase select Validation endscan * show error message if not empty(lcErrorText) if llError * Can't save; error saving MessageBox("No se pudo guardar:" + chr(13) + chr(13) + lcErrorText,; 16, "Error al guardar") else * Warning; do you want to save anyway? llError = MessageBox("Advertencia al guardar:" + chr(13) + chr(13) + lcErrorText; + chr(13) + "¿Quiere guardar de todos modos?",; 4 + 48 + 256, "Advertencia al guardar") # 6 endif ** Mensaje combinado, anterior *!* MessageBox(iif(llError, "No se pudo guardar:", "Advertencia al guardar:") + chr(13) + chr(13); *!* + lcErrorText + iif(llError, "", chr(13) + "Se guardaron los cambios."),; *!* 16, iif(llError, "Error al guardar", "Advertencia al guardar")) *MessageBox(iif(llError, "Can't save:", "Warning on save:") + chr(13) + chr(13); * + lcErrorText + iif(llError, "", chr(13) + "Changes saved."),; * 16, iif(llError, "Error on save", "Warning on save")) endif * restore environment and return success status use in validation select (lnOldAlias) set exact &lcOldExact return not llError ENDFUNC