Just found out something I didn't know re scripting.
If you are in the object about which you are scripting, you can omit the object name.
So, for example, if this is the ValueChanged event for FieldA, you DON'T need:
FieldA.Fill.Color.Red := 255 . etc
But can get away with:
Fill.Color.Red := 255 .
Show () .
Which saves some typing!
(I will also save some typing by NOT going back to old articles and blogs to adjust code. Sorry!)
More importantly, it means that a lot of scripts can be generic, as long as they reference the properties and methods of the current object, and that you are pasting them into objects that have those properties and methods.
Showing posts with label Scripting. Show all posts
Showing posts with label Scripting. Show all posts
Thursday, 11 February 2010
Wednesday, 20 January 2010
Letters, Loopers and Some Very Strange Relationships
Time for some daft, ‘out there’ ideas … and a bit of fun.
Here’s the goal: let’s imagine an environment, such as a busy, messy factory floor, where gloves and mess make it impossible to use a keyboard.
So you have a touch-sensitive screen, covered with a suitable protective layer, and want to give users the ability to look up something by typing in a reference number or keyword.
You need an on-screen keyboard, and because you love doing things in Ffenics or DataEase, you’re determined to create that keyboard using your favourite software.
Something like this:
So, we have a label, and field into which a value can be typed. There’s a funny arrow button to the right which is masquerading as a backspace button, a rough QWERTY keyboard plus integers, a blue bar representing the space bar, and a button labelled ‘Go’ which could be used to start a report that returns whatever it is supposed to return.
I’m using a couple of tricks here, including one that I’m surprised I’ve only just started to use regularly.
If you’re looked at other articles by me in which some set of buttons with letters from the alphabet is used, you should know that I have not wasted time and tightened every muscle in my back by laying out 36 buttons, each with their own set of scripts, to represent the keyboard. You should guess that I’m using a subform (just for the QWERTY letters and numbers; everything else is on the main form). And that the subform is build on my swiss-army-knife-of-a-dataset, Looper.
Or maybe you haven’t a clue what I’m on about. So let me explain.
Looper is a table of integers. To be precise, it is a table of ordinal numbers -- that is, integers in order. Why I call it Looper is my own business.
The area on screen is a 10 x 4 subform. Each record in that subform is a number from 1 to 40, the first 40 records in Looper.
The object with the appropriate letter displayed is a ‘layout-only virtual’, that is, a field that only exists on this document. It happens to be called vLetter, is one character long, and is derived:
midc ( "1234567890QWERTYUIOPASDFGHJKL ZXCVBNM " , LoopNo , 1 )
That odd string is the set of characters from your QWERTY keyboard, starting with the numbers across the top, then each row of upper case letters. The spaces towards the end help with the indenting of the keyboard.
LoopNo is our actual field in the form, the one containing the ordinal integer. The derivation basically finds the corresponding letter for the key. For example, the letter ‘R’ is in the second row and is four columns over on the keyboard; the ordinal number behind that record will therefore be 14, and the 14th letter in my string is the letter ‘R’.
As I said, these are records in a subform. But what’s the nature of the relationship? Well, this is one of my new tricks: the main form and Looper match based on … NO match fields.
Yes, they match on nothing. Nada. Zilch. And as a result, ALL records in the subform display. Try it and see with any old forms.
Now, Looper probably contains several thousand integers. But because I have removed the scrollbar from the subform, we only see the first 40 records. (Actually, if I had used a button instead of a text object for the letters, we’d have to deal with a minor issue about scrolling because the button can get focus, but let’s worry about that some other time.)
The letter field has two scripts: a clicked event for adding to the string of text in the main form’s ‘code’ field, and a ValueLoaded event to hide the field if its value is a space (to make the layout look a bit more like a keyboard).
The clicked event script is:
define "t" number .
Customer.FirstName.Value := concat ( Customer.FirstName.Value ,
if ( getarray ( 1 ) = "SpacePending" , " " , "" ) , vLetter.Value ) .
t := setarray ( 1 , "" ) .
Customer.FirstName.Show () .
In a recent blog post I covered how to update values between sub and main forms using scripts. Basically, we are adding the value of the letter to the end of the value already in our main form field.
Spaced Out
The getarray bit obviously needs explaining. It turns out that when you concat a space to the end of a field, the value in the field seems to immediately be trimmed of the trailing space.
The dark blue bar, as I mentioned above, is the space key. When this is clicked, this script:
define "t" number .
t := setarray ( 1 , "SpacePending" ) .
justs sets a flag, using array #1, to indicate that we are expecting a space. When a letter is clicked, we can then first insert such a pending space before the letter, and get around the trimming of spaces described.
Each letter also resets array #1 to blank, effectively meaning that the space is no longer pending.
The valueloaded script on the letter field is:
if vLetter.Value = " " then
vLetter.Hide () .
else
vLetter.Show () .
end
Two other things need mentioning. The first is that I found issues with Ffenics if the record contained no actual fields from the form. So Looper’s LoopNo is actually on the record, scrunched up in the top left corner. It has its new display option ‘hide’ checked, which means that it is never actually made visible. DataEase for Windows scripts didn’t need underlying fields present.
The other item is the backspace button. This deletes one character at a time from the string. Its script is:
Customer.FirstName.Value := firstc ( Customer.FirstName.Value ,
length ( Customer.FirstName.Value ) - 1 ) .
Customer.FirstName.Show () .
Of course, you might want to have more characters than I’ve chosen. I’m sure someone could have some fun working out how to put the display into upper or lower case, or to imitate the keyboards found on some PDAs and smart phones. You could also add a ‘Clear All’ button. And another intriguing problem would be to have more than one field for data-entry. That’s your homework.
Time to implement this from scratch: less than one hour. Click title for PDF version from my website.
Here’s the goal: let’s imagine an environment, such as a busy, messy factory floor, where gloves and mess make it impossible to use a keyboard.
So you have a touch-sensitive screen, covered with a suitable protective layer, and want to give users the ability to look up something by typing in a reference number or keyword.
You need an on-screen keyboard, and because you love doing things in Ffenics or DataEase, you’re determined to create that keyboard using your favourite software.
Something like this:
So, we have a label, and field into which a value can be typed. There’s a funny arrow button to the right which is masquerading as a backspace button, a rough QWERTY keyboard plus integers, a blue bar representing the space bar, and a button labelled ‘Go’ which could be used to start a report that returns whatever it is supposed to return.
I’m using a couple of tricks here, including one that I’m surprised I’ve only just started to use regularly.
If you’re looked at other articles by me in which some set of buttons with letters from the alphabet is used, you should know that I have not wasted time and tightened every muscle in my back by laying out 36 buttons, each with their own set of scripts, to represent the keyboard. You should guess that I’m using a subform (just for the QWERTY letters and numbers; everything else is on the main form). And that the subform is build on my swiss-army-knife-of-a-dataset, Looper.
Or maybe you haven’t a clue what I’m on about. So let me explain.
Looper is a table of integers. To be precise, it is a table of ordinal numbers -- that is, integers in order. Why I call it Looper is my own business.
The area on screen is a 10 x 4 subform. Each record in that subform is a number from 1 to 40, the first 40 records in Looper.
The object with the appropriate letter displayed is a ‘layout-only virtual’, that is, a field that only exists on this document. It happens to be called vLetter, is one character long, and is derived:
midc ( "1234567890QWERTYUIOPASDFGHJKL ZXCVBNM " , LoopNo , 1 )
That odd string is the set of characters from your QWERTY keyboard, starting with the numbers across the top, then each row of upper case letters. The spaces towards the end help with the indenting of the keyboard.
LoopNo is our actual field in the form, the one containing the ordinal integer. The derivation basically finds the corresponding letter for the key. For example, the letter ‘R’ is in the second row and is four columns over on the keyboard; the ordinal number behind that record will therefore be 14, and the 14th letter in my string is the letter ‘R’.
As I said, these are records in a subform. But what’s the nature of the relationship? Well, this is one of my new tricks: the main form and Looper match based on … NO match fields.
Yes, they match on nothing. Nada. Zilch. And as a result, ALL records in the subform display. Try it and see with any old forms.
Now, Looper probably contains several thousand integers. But because I have removed the scrollbar from the subform, we only see the first 40 records. (Actually, if I had used a button instead of a text object for the letters, we’d have to deal with a minor issue about scrolling because the button can get focus, but let’s worry about that some other time.)
The letter field has two scripts: a clicked event for adding to the string of text in the main form’s ‘code’ field, and a ValueLoaded event to hide the field if its value is a space (to make the layout look a bit more like a keyboard).
The clicked event script is:
define "t" number .
Customer.FirstName.Value := concat ( Customer.FirstName.Value ,
if ( getarray ( 1 ) = "SpacePending" , " " , "" ) , vLetter.Value ) .
t := setarray ( 1 , "" ) .
Customer.FirstName.Show () .
In a recent blog post I covered how to update values between sub and main forms using scripts. Basically, we are adding the value of the letter to the end of the value already in our main form field.
Spaced Out
The getarray bit obviously needs explaining. It turns out that when you concat a space to the end of a field, the value in the field seems to immediately be trimmed of the trailing space.
The dark blue bar, as I mentioned above, is the space key. When this is clicked, this script:
define "t" number .
t := setarray ( 1 , "SpacePending" ) .
justs sets a flag, using array #1, to indicate that we are expecting a space. When a letter is clicked, we can then first insert such a pending space before the letter, and get around the trimming of spaces described.
Each letter also resets array #1 to blank, effectively meaning that the space is no longer pending.
The valueloaded script on the letter field is:
if vLetter.Value = " " then
vLetter.Hide () .
else
vLetter.Show () .
end
Two other things need mentioning. The first is that I found issues with Ffenics if the record contained no actual fields from the form. So Looper’s LoopNo is actually on the record, scrunched up in the top left corner. It has its new display option ‘hide’ checked, which means that it is never actually made visible. DataEase for Windows scripts didn’t need underlying fields present.
The other item is the backspace button. This deletes one character at a time from the string. Its script is:
Customer.FirstName.Value := firstc ( Customer.FirstName.Value ,
length ( Customer.FirstName.Value ) - 1 ) .
Customer.FirstName.Show () .
Of course, you might want to have more characters than I’ve chosen. I’m sure someone could have some fun working out how to put the display into upper or lower case, or to imitate the keyboards found on some PDAs and smart phones. You could also add a ‘Clear All’ button. And another intriguing problem would be to have more than one field for data-entry. That’s your homework.
Time to implement this from scratch: less than one hour. Click title for PDF version from my website.
Labels:
DataEase for Windows,
Ffenics,
Looper,
Scripting
Tuesday, 12 January 2010
... And Looking Down
Following from my last post we should consider how you use script to point from an object in a main form to a specific row in a subform.
Here, life is not so rosy. Yes, this script will copy main form value to subform:
MySubform.MySubformField.Value := MainFormField.value .
MySubform.MySubformField.show () .
The trouble is, this will only update the first visible subform row. Now, if you're only displaying one subform record, that might not be an issue. But otherwise, whatever is the top row currently visible is the one that is targeted. Not the first in the dataset, note: the first visible. Scroll the list so that the top one pops off and you'll now be affecting the value in the row that was previously below.
Now, I'm not entirely sure why one would want to do such a thing in the first place, but no doubt someone will want to do something like this. I therefore post for completeness.
If the goal was to change the value in all sub records, you could do this using a procedure instead, followed by use of the RefreshScreen action (all existing records will magically be updated). You could also include the field you want to copy to the subform records in a relationship, and use that relationship for the subform.
Thoughts, anyone?
Here, life is not so rosy. Yes, this script will copy main form value to subform:
MySubform.MySubformField.Value := MainFormField.value .
MySubform.MySubformField.show () .
The trouble is, this will only update the first visible subform row. Now, if you're only displaying one subform record, that might not be an issue. But otherwise, whatever is the top row currently visible is the one that is targeted. Not the first in the dataset, note: the first visible. Scroll the list so that the top one pops off and you'll now be affecting the value in the row that was previously below.
Now, I'm not entirely sure why one would want to do such a thing in the first place, but no doubt someone will want to do something like this. I therefore post for completeness.
If the goal was to change the value in all sub records, you could do this using a procedure instead, followed by use of the RefreshScreen action (all existing records will magically be updated). You could also include the field you want to copy to the subform records in a relationship, and use that relationship for the subform.
Thoughts, anyone?
Labels:
DataEase for Windows,
Ffenics,
OCL,
OML,
Scripting
Wednesday, 2 December 2009
Out of Sight, Not Out Of Mind: Thoughts on Ffenics Object Scripting
If you want to pass, say, the ID for a record to the setglobal function using Ffenics or DataEase scripting, you need to include some field object on screen.
So a typical scenario might be to create a virtual in your Ffenics form derived from the ID value (or to add a 'layout only field' to an aspect), place this field on the screen, and refer to its 'value' property in the script.
You don't necessarily want the actual data to appear to the user, so somehow you have to style it so that it is not visible, and scrunch it up in a corner somewhere to keep it out of range of the things you actually want the user to see. If it overlaps with visible objects, it may partially obscure them. And because you have set it to look like it is not there, it's hard to spot it when in designer view.
The new 'Hide' option on the Ffenics display dialog for an object does away with this, and can both simplifiy and help with development. By placing a field on screen and then checking this property, you can still reference the value it contains, but the object, as you'd imagine, simply does not appear. In addition, it can overlap with other visible objects without causing runtime oddities in appearance.
And you can give such objects a 'hidden field' style that, in designer view, makes them totally obvious (give them a nice bright red background, why don't you) so you can spot them when you're building your wonderful aspect, safe in the knowledge that they will be forever invisible to the user.
So a typical scenario might be to create a virtual in your Ffenics form derived from the ID value (or to add a 'layout only field' to an aspect), place this field on the screen, and refer to its 'value' property in the script.
You don't necessarily want the actual data to appear to the user, so somehow you have to style it so that it is not visible, and scrunch it up in a corner somewhere to keep it out of range of the things you actually want the user to see. If it overlaps with visible objects, it may partially obscure them. And because you have set it to look like it is not there, it's hard to spot it when in designer view.
And you can give such objects a 'hidden field' style that, in designer view, makes them totally obvious (give them a nice bright red background, why don't you) so you can spot them when you're building your wonderful aspect, safe in the knowledge that they will be forever invisible to the user.
Friday, 13 November 2009
Naming Conventions
Ffenics consultants will nag on about not using reserved words, adopting single word naming conventions and so on, but the truth is that DataEase and Ffenics are so resillient to these mistakes that 95% of the time you can probably get away with them.
We'll still laugh at you, of course, unless it's your round.
But I did just come across an instance where idiosyncratic nomenclature aims its teeth at your derriere: punctuation such as brackets (or parenthesis) confuse attempts to write object scripts.
Every book on computing you'll ever read will tell you to stick to single word names, but if you managed to skip those pages, or are looking after an app created by AN Other, then there is a workaround: use the 'object name' option on the field definition dialog, and change the object name at least to a single word.
Ff uses the field name from the form/table to be the default name for the object on a form or aspect that displays the data. It also uses the same name for summary field objects. You cannot have objects with the same name in the same container, but the corresponding summary object for a regular field object will be created in the form container, not in the record container, so there is no immediate confusion. Still, not a bad idea, if you are likely to do a lot of scripting on a document that has summary variables, to rename them to something easier to spot in the script object list.
We'll still laugh at you, of course, unless it's your round.
But I did just come across an instance where idiosyncratic nomenclature aims its teeth at your derriere: punctuation such as brackets (or parenthesis) confuse attempts to write object scripts.
Every book on computing you'll ever read will tell you to stick to single word names, but if you managed to skip those pages, or are looking after an app created by AN Other, then there is a workaround: use the 'object name' option on the field definition dialog, and change the object name at least to a single word.
Subscribe to:
Posts (Atom)