dansmith65 Posted January 13, 2012 Posted January 13, 2012 I was just writing some scripts that created related records, and came across an interesting error trapping technique that I thought I'd share... Sample script before error trapping: Set Variable [$id; invoice::id] Go to Layout ["lineItems"] New Record/Request Set Field[lineItems::invoiceID; $id] Set Field[lineItems::anotherField; "some data"] Set Field[lineItems::andAnotherField; "some more data"] Go to Layout [original layout] Here are a few possible error scenarios: user does not have privileges to create new records, script would error at the New Record/Request step, then ask the user if they want to continue the script or cancel it. If the user clicked continue, then it would modify the active line item record (if the user's privileges allowed it). if the found set = 0 when the script started, then the $id variable would be empty, so an empty value is set to the lineItems::invoiceID field. When the record is committed, the fields validation would be triggered (this field should be validated to require a value). The conclusion here is that either the New Record/Request step or any of the Set Field steps can produce an error, and the script should skip the rest of the record-editing steps, and skip to the Go to Layout step if an error occurs. Here is one way to do that... Allow User Abort [OFF] makes sure the script runs to the end, even if an error occurs Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] stops editing record, and saves the error Commit Records/Requests [No dialog] some field validation won't be evaluated until the record is commited, without this step, the validation error will occur after the Go to Layout step Revert Record/Request [No dialog] If an error did occur, remove the newly created record It's a strange use of the loop/exit loop if/end loop steps, but I like it much better than a bunch of nested If statements. Allow User Abort [OFF] Set Variable [$id; invoice::id] Go to Layout ["lineItems"] Loop New Record/Request Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] Set Field[lineItems::invoiceID; $id] Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] Set Field[lineItems::anotherField; "some data"] Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] Set Field[lineItems::andAnotherField; "some more data"] Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] Commit Records/Requests [No dialog] Exit Loop If [Get( LastError ) <> 0 and Let($LastError = Get( LastError ); true)] Exit Loop If [True] End Loop If [not IsEmpty( $LastError ) and $LastError <> 0] Revert Record/Request [No dialog] Show Custom Dialog ["Error"; "Line item record was not created."] End If Go to Layout [original layout]
Vaughan Posted January 15, 2012 Posted January 15, 2012 Not sure I like the loop structure. Unnecessary, complicates the code. Trap the New Record step. If a new record is created, the Set Fields steps should be OK. Trap the Commit Record step. Field Validation may prevent the record from being saved. Running the script in a empty found set is not an error as such, but it is something that should be checked for. Allow User Abort [OFF] If [ Get( FoundCount ) = 0 Exit Script [] End If Set Variable [$id; invoice::id] Go to Layout ["lineItems"] Set Error Capture [ on ] New Record/Request Set Variable [ $error ; Get( LastError ) ] Set Error Capture [ off ] If [ $error = 0 ] Set Field[lineItems::invoiceID; $id] Set Field[lineItems::anotherField; "some data"] Set Field[lineItems::andAnotherField; "some more data"] Set Error Capture [ on ] Commit Records/Requests [No dialog] Set Variable [ $error ; Get( LastError ) ] Set Error Capture [ off ] If [ $error <> 0 ] Revert Record [ no dialog ] End If End If Go to Layout [ original layout ] If [ $error <> 0] Show Custom Dialog ["Error"; "Line item record was not created."] End If
dansmith65 Posted January 28, 2012 Author Posted January 28, 2012 Thanks for your feedback Vaughan, it made me think about this a little more. I realized that I don't know what error's could occur during a set field step, as opposed to a commit record step. The only errors I can think of that would happen durring the set field step are for field validation or insufficient privileges. I'm sure there are other errors that I can't think of though. (Actually, if using set field by name, that could error if the field does not exist.) Regarding field validation errors, some validation options error when the field is set, others when the record is commited... Validation option ................ when error occurs ---------------------------------------------------- Strict data type ................. set field Not Empty/Unique/Existing ........ commit record Value List ....................... set field In Range ......................... set field By Calculation ................... commit record Max # of Char's .................. set field * There is no error on the set field step if "Only during data entry" validation option is selected. An error thrown on the set field step does not generate a FileMaker error dialog, whereas an error thrown on the commit record step does. After seeing this, I still think it's best to test for an error after setting every field, otherwise your script could be failing to set field data and you wouldn't even know about it. I think it's debatable if the Loop method I mentioned in my first post is the best way to do this though. The biggest problem I see with it is that you are using a loop for something it wasn't meant for, which is confusing. But what's the alternative? A nested If/else for every set field step? That seems much worse to me. Basically, what I have done with the loop steps is created a Try/Catch exception handling system: http://www.w3schools...p_exception.asp
dansmith65 Posted February 24, 2012 Author Posted February 24, 2012 I should have tested for this earlier, but I just realized that the 'Exit Loop If' step does not clear the value of Get( LastError ), so I don't need to save the error to a variable like in my first example. I modified the script below to reflect this. Allow User Abort [OFF] Set Variable [$id; invoice::id] Go to Layout ["lineItems"] Loop New Record/Request Exit Loop If [Get( LastError ) <> 0] Set Field[lineItems::invoiceID; $id] Exit Loop If [Get( LastError ) <> 0] Set Field[lineItems::anotherField; "some data"] Exit Loop If [Get( LastError ) <> 0] Set Field[lineItems::andAnotherField; "some more data"] Exit Loop If [Get( LastError ) <> 0] Commit Records/Requests [No dialog] Exit Loop If [Get( LastError ) <> 0] Exit Loop If [True] End Loop If [Get( LastError ) <> 0] Revert Record/Request [No dialog] Show Custom Dialog ["Error"; "Line item record was not created."] End If Go to Layout [original layout] Also, I've been using this technique lately and it came in handy when I was writing a new script and picked the wrong table occurrence for a set field step; rather than the script hiding the error and leaving me wondering what went wrong, it gave me an error, and exited without continuing, which helped me debug the script during development.
Recommended Posts
This topic is 4657 days old. Please don't post here. Open a new topic instead.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now