Write a script that uses a series if If/Else If steps that basically do the following:
If (IsEmpty (Field))
Set Field (Value A)
If (Field = Value A)
Set Field (Value B)
Else If (Field = Value B)
Set Field = (Value C)
Else If (Field = Value C)
Set Field = (Value D)
Else If (Field = Value D)
Set Field = (Value A)
When the field is empty and you first click the button, the script sets the field to value "A". Then each succesive click changes the value of the field to the next value in the sequence. When it gets to the last value ("D"), it cycles back to the first value ("A"). Keep clicking and the values keep cycling. No need for a drop-down menu or Value List.
I would rather not hard-code the value and it would be good to allow for increased number of values without having to change the script. Replace 'button' with your value list name (it can be custom value list or values from field). I think the calculation can be prettied up but I don't have the time right now; besides, this way, the thinking is clear as you read through it. A single script-step using Set Field will address it all ... the calculation does all the evaluating.
Set Field [ yourField ; with the following calculation ]
Let ( [
txt = buttons::text ;
vl = ValueListItems ( Get ( FileName ) ; "button" ) ;
temp = Substitute ( ¶ & vl & ¶ ; ¶ & txt & ¶ ; "¶~¶" ) ;
pos = Position ( temp ; "~" ; 1 ; 1 ) + 2 ;
newlist = Middle ( temp ; pos ; Length ( vl ) )
IsEmpty ( txt ) or IsEmpty ( newlist ) ; GetValue ( vl ; 1 ) ; GetValue ( newlist ; 1 )
If yourField is empty OR if yourField currently has the LAST entry, it will set the entry to the first in the value list. Otherwise it will sequence through all the values. Calculation updated to protect from duplicate beginning words in different value list lines.
I tried out your calculation and it works perfectly, but I have no idea how or why! I'm not a Filemaker guru, so excuse my ignorance, but what exactly do the temp, pos and newlist variables do? And the ~ symbol?? If you have time, a breakdown of what's actually happening with each step of the calculation would be much appreciated! If not, no worries, I'll ponder it and see if I can work out why it works.
Using variables within a Let() statement allows four things:
1) Instead of making a calculation more cluttered by using yourtable::yourfield through the calc, we can name it ONCE as something simple, even a simple t. It simply is easier to read.
2) Once a variable is evaluated, it doesn't have to be evaluated again for the duration of the calculation. So if I want the current date, I declare a variable as d = Get ( CurrentDate ) and then simply refer to d throughout the calc and it isn't evaluated over and over - only once.
3) You can sequence your work, which is what I did (in a rather simple and clumsy manner). So you can do this:
Let ( [
firstStep = change a text string like this ;
secondStep = change firstStep like this ... and so forth
4) You can specify true variables (which can persist outside of the Let() ... for instance, layout-level variables, global variables ($ and $$).
... and you can also have Let() within Let(). When viewing a calc or writing a more complex calc, I always create test file to grab my thinking and I break each piece into a separate calculation so I can watch the results and I did the same in this situation so I will attach my actual test file. I added the calculations next to the fields that I had created to watch my test results and I added my thinking as I wrote the calculation as well.
Watching calculations in action fascinates me and I many times break them into pieces to see how they interact. So, as you click the SEQUENCE button, watch the temp field and read the calc. Then watch the other pieces change.
The file can be downloaded from: http://www.4shared.com/file/1egPcTUl/buttons.html
There are other methods and I am sure there are more elegant approaches and cleaner calcs but this is what came to me today and it's my day off. :-)
I think that you have to re-think about your "temp" variable.
Something like this:
txt = YourTable::YourField ;
vl = ValueListItems ( Get ( FileName ) ; "button" ) ;
newlist = Filter ( Substitute ( ¶ & vl & ¶ ; ¶ & txt & ¶ ; "X" ) ; "¶X" ) ;
pos = Position ( newlist ; "X" ; 1 ; 1 )
GetValue ( vl ; Mod ( pos ; ValueCount ( vl ) ) + 1 )
Yes, I should have wrapped with carriage return and I knew better; after all, we were both taught by the best. Uhm, I used tilde for a reason. If the value list contains X then your calculation will fail.
I have replaced my demo file wrapping with carriage return to protect from EVERY situation.
I do not think so... if the value list contains an X value, it will be changed to an X value.
Try your calculation with this value list.
Your original calculation broke when X existed in the field. Your current calculation, the one you later wrapped with Mod(), will produce Two-Edged when text is empty and it won't get past that (I copied both your calcs exactly for my tests). Anyway, my file is there and it works. Thanks for pointing out the carriage return issue. I would have noticed it after some rest.
Yes, I see...
It was the Filter() function that let other Xs ( the X of other values ) to pass, not the Substitute( ).
it's a very beautiful thing! but I can't see a real world application for it ... intrigued to know what field (no pun intended) Mitch works in ?
Many thanks, LaRetta , for providing a file that shows the steps of the calc. I've used some Let () calcs in my own solutions, so I understand the principles of them, but the calc you've demonstrated is a level above my knowledge and experience so I'm still trying to get my head around it! Needless to say, I've saved your file and will study it more closely later this week.
Thanks again for the lesson and demo!
Well, they all worked for me....
Thanks very much. As for the field I work in..... I am not a programmer of any sort, just someone who likes to dable in writing databases.
At the moment I am writing a database to maintain research records. Hence the question. The ability to change a label attached to a field to suit the database user has some great application.