Tips   >   Misc   >   Misc
There is no need to compare the expression value to kTrue or kFalse for any expression in Omnis Studio which returns true or false.
Here are some code examples to clarify this.
; Calculate the number of selected lines.
Do ListVar.$sendall(LineCount.$assign(LineCount+1),$ref.$selected=kTrue)
; Using $ref.$selected is shorter and is the same as using $ref.$selected=kTrue
Do ListVar.$sendall(LineCount.$assign(LineCount+1),$ref.$selected)
; Using not($ref.$selected) to count the unselected lines.
Do ListVar.$sendall($ref.value.$assign(10),not($ref.$selected))
; Check the return flag.
If FlagOK=kTrue
; Do something
End If
; Using FlagOK is the same as FlagOK=kTrue
If FlagOK=kTrue
; Do something
End If
; Use not(FlagOK) to test for FlagOK=kFalse
If not(FlagOK)
; We have a problem.
End If
; Check if the file exists.
Do FileOps.$doesfileexist(Path) Returns bFileExists
If bFileExists
; Do something
End If
; You can put the expression in an If calculation since it evaluates to true or false.
If FileOps.$doesfileexist(Path)
; Do something
End If
; Check if a certain name is in the list.
Do ListVar.$search($ref.FirstName='Dawid',1,0,0,0) Returns LineNum
If LineNum>0
; Do something
End If
; You can put the expression in an If calculation since it evaluates to a numeric value.
If ListVar.$search($ref.FirstName='Dawid',1,0,0,0)
; Do something
End If
You might run into a situation where you want to call a class method without first creating an instance of the class.
The trick for doing this is to use the Do code method command. The Do code method is not limited to ; it can be pointed to the class method of any type of class.
Do code method [$clib().$name].wWinClassName.MethodName (pParam1,pParam2)
I'm not sure why you would need to do this... this style of code is something the object-oriented programming police might pull you over for. You should be using a public method of a class instance.
Omnis Studio allows you to change the font sizes in most of the IDE (Interactive Developer Environment) windows. This can be especially helpful if you are doing a presentation.
To change the font size of the code list, methods treelist, Property Manager, Catalog, etc.
The changed font size will only be temporary. If you close and reopen the IDE window, the font size will revert to the original size.
To save the font size for the IDE window, right-click on the window and select .Here's a word of advice about code class... don't use them. (Okay, that was 3 words.)
When I started learning Omnis Studio I tried object classes and said to myself, "This is too hard, Code Classes are much easier to work with and call, I'm sticking with code classes". Six months later at my first Omnis Conference, Geir Fjaerli convinced me to use object classes. The statement he made proved true, "Anything you can do with a code class, you can do better with an object class."
Code classes are a slippery slope that draws you away from object-oriented programming, and back into Omnis Classic style coding. (There is a difference.) Omnis Studio will admit to you they only included code classes to make it easier for converting from Classis to Studio. I was told the original design of Omnis Studio did not include code classes.
There are several problems you will run into with code classes:
If you ever need to print checks, you'll need to convert the dollar value of the check to text.
For example, you may need to convert 550.25 to five hundred and fifty -------- 25/100
You can download a free library called convertNumberToText from the downloads section of the studiotips.net website.
The library contains an object class which you can copy to your application and then instantiate and send messages to.
Calculate Number as 11578.97
Do oConvertNumberToText.$convertNumberToText(Number) Returns Text
To delete an instance variable from a class, you right-click on the variable in the variables pane and select
in the context menu. As long as the variable is not used in any code, Omnis Studio will prompt you with a dialog. In some rare situations, Omnis Studio won't let you delete an instance variable, even though you have deleted every piece of code that contains the instance variable. comes up empty and you've closed and reopened the class, but the stubborn ivar can't be deleted. One trick for getting rid of a stubborn instance variable is to drag it from the variables pane to the variables pane. For some reason, once you've done that Omnis Studio allows you to delete the class variable.The $desc property is found is several different location in Omnis Studio:
The class desciption can be modified by selecting the class in the $desc property.
> pressing F6 > selecting the tab and clicking on theThe method description for public methods (prefixed with $ character) can be viewed/modified through the . In the right-click on a class > select . At the bottom of the click the tab to view and modify the description property of the method.
Private and public method descriptions up to 255 characters can be edited in the method editor. Select the method in the method editor, then click on the grey field just below the code list.
The variable descriptions are accessed through the variables pane of the method editor.
Click the button to find out the maximum length of each $desc property.This obsure little command redirects a command to a method of another instance with the same method name.
You could have a shell window which has an $editRecord method that redirects the message to the current subwindow.
The message could be forwarded as follows:
Do rSubWin.$editRecord(pPrimaryKey) Returns FlagOK
or using redirect
Do redirect rSubWin Returns FlagOK
An interesting feature of Do redirect is that you do not have to declare any parameters. Do redirect passes the incoming parameters without declaring them. Cool!
You can only redirect to a method of the exact same name.
The install size of Omnis Studio v4.2 is quite a bit bigger on the Mac OS X version than the Windows version.
A lot of it is the Mac xcomps, which for some reason all seem to link in a large library of common code. The simplest xcomp ends up being over 400K. You can look through them and discard those that your app doesn't use, notably the oXML at 6.4MB, DAMs you aren't using, docView, etc. - for every 2 xcomps you can remove you save a meg - and if you don't use graphs you can lose the Frameworks folder to save another 5MB. The webclient.plugin in the localclient folder can save almost 9MB if you don't use remote forms.
By trimming out things like that, you can get a 4.2 runtime plus library and data files down to a 50MB downloadable dmg file containing an Apple installer. The previous version, non-universal and not nearly as well cleaned-out, was 32MB.
The above info was provided by Kelly Burgess.Omnis Studio is localized for different languages. The localized versions replaces the Yes/No/OK prompt button text wtih the appropriate local language text. It may also default to different separator characters in $prefs.$separators.
$separators is a 5 character string.The characters in this string are:
Character 1: the decimal point character
Character 2: the decimal number thousands separator
Character 3: the function parameter separator
Character 4: the import/export decimal point character
Character 5: the import/export comma delimiter character
I ran into trouble with the function parameter separator and the German localized version.
In the English version character 3 is a , comma.
In the German version character 3 is a ; semi-colon.
In the English version concatentate looks like this:
Calculate FullName as con(FirstName,' ',LastName)
If you opened the same library in the German version, you code would look like this:
Calculate FullName as con(FirstName;' ';LastName)
Your normal Omnis code will run without a problem in the English or German version. The problem will be write some code that assumes what the separator will be. The problem I hit in StudioTips was with a replaceall() function.
I wanted to determine then text of the tab strip which the user clicked on. The $event code for the tab strip object was something like this.
CODE THAT BROKE WHEN USING THE GERMAN VERSION OF OMNIS STUDIO.
On evClick
Find out the text string represented by the tab strip.
Calculate TabStripTabs as irTabStrip.$tabs
e.g. About StudioTips, Basics Tutorial, Miscellaneous
Convert the string for use in a pick statement. Replace each comman with quote-comma-quote ','
Calculate ReplaceValue as "','" ;; quote-comma-quote
Calculate PickString as replaceall(TabStripTabs,",",ReplaceValue)
e.g. About STP',' Basics Tutorial',' Miscellaneous
Add opening and closing quotes.
Calculate PickString as con("'",PickString,"'")
Prepare the pick() statement string to and evaluate it.
Calculate EvalString as con('pick(',pTabStripNum-1,',',PickString,')')
Calculate TabStripName as eval(EvalString)
The above code failed with the German localized version because I had assumed the comma separator in the replaceall() function, and in the eval(pick()) function.
FIXED CODE THAT WORKS WITH THE ENGLISH AND GERMAN VERSIONS OF OMNIS STUDIO.
To fix above code I modified it as follows:
On evClick
Find out the text string represented by the tab strip.
Calculate TabStripTabs as irTabStrip.$tabs
e.g. About StudioTips, Basics Tutorial, Miscellaneous
Find out the Omnis Studio localized function separator.
Calculate FnSep as mid($prefs.$separators,3,1) ;; English comma, German semi-colon
Convert the string for use in a pick statement. Replace each comman with quote-comma-quote ','
Calculate ReplaceValue as con("'",FnSep,"'") ;; quote-FnSep-quote
Calculate PickString as replaceall(TabStripTabs,",",ReplaceValue)
e.g. About STP',' Basics Tutorial',' Miscellaneous ;; English
e.g. About STP';' Basics Tutorial';' Miscellaneous ;; German
Add opening and closing quotes.
Calculate PickString as con("'",PickString,"'")
Prepare the pick() statement string to and evaluate it.
Calculate EvalString as con('pick(',pTabStripNum-1,FnSep,PickString,')')
Calculate TabStripName as eval(EvalString)
TESTING YOUR OWN APPLICATION
Testing your own application for different localized version of Omnis Studio is quite simple to do.
In the Omnis Studio > local folder, there is a file named omnisloc.df1.
You can download a free zip file containing the English, French, German, and Swedish versions of the omnisloc.df1 file from the downloads section of the studiotips.net website.
www.studiotips.net/downloadsI wanted to be able to open PDF files from Omnis Studio.
MAC PLATFORM
On the Mac platform that's pretty easy to do:
Send Finder event {Open Files (FilePath)}
Note: This Omnis command does not affect the flag. So you can't test flag true or false.
WINDOWS PLATFORM
Life gets a little more complicated on the Windows platform. Tech Support was kind enough to provide me with sample code.
You have to use the Omnis commands Register DLL and Call DLL. These Omnis commands are not available to you in Omnis Studio when you are using a Mac.
Here's what we ended up with for the Windows platform:
Register DLL ("SHELL32.DLL","ShellExecuteA","JJCCCCJ")
Call DLL ("SHELL32.DLL","ShellExecuteA",0,"open",FilePath,"","",0) Returns HINST_EXPLORER
NOTES:
X250825050 ("SHELL32.DLL","ShellExecuteA","JJCCCCJ")
X250825051 ("SHELL32.DLL","ShellExecuteA",0,"open",FilePath,"","",0) Returns HINST_EXPLORER
CROSS-PLATFORM CODE
Putting it together in a Switch/Case for cross-platform use, we end up with the following:
; Prompt the user to select a PDF file.
Do FileOps.$getfilename(FilePath,'Select a PDF file','*.pdf') Returns FlagOK
If not(FlagOK)
Quit method kFalse
End If
; Open the file, using code for the specific platform.
Switch sys(6)
Case 'M','X' ;; Mac or Mac OS X
Send Finder event {Open Files (FilePath)}
Case 'W','N' ;; Windows or NT
Register DLL ("SHELL32.DLL","ShellExecuteA","JJCCCCJ")
Call DLL ("SHELL32.DLL","ShellExecuteA",0,"open",FilePath,"","",0) Returns Hinst_Explorer
If not(Hinst_Explorer)
OK message (Icon) {Opening the file failed.}
Quit method kFalse
End If
Default
OK message [sys(85)] (Icon) {Open file code not written for sys(6) = [sys(6)]////Please notify the programmer.}
Quit method kFalse
End Switch
Quit method kTrue
A word of caution about the Optimize method command... Omnis programmers have been burned by this command.
The documentation says you can add this command to the first line of a method which you call frequently. The optimized version of the method will be stored in memory and used each time the method is called.
However, Optimize method has not proven to be reliable.
It caused my payroll program to completely crash Omnis Studio when I added it to a method which included twelve Switch/Cases. Others have reported various problems.
Personally, I didn't find any speed improvement. I think Optimize method had its purpose when we were running slow clunky computers. But in this age of faster and faster computers, Optimize method, has much less impact.
You decide whether or not you want to use Optimize method. For my peace of mind, I won't be using it in any application I write.The Mac OS X Aqua Interface draws a thick bluish border around the entry field which has the focus. This can be a problem if you have entry fields that are tightly spaced, or if you are using a different method for showing which field has the current focus.
The Omnis Studio preferences allow you to turn on the Mac OS X system focus.
You can set this preference in your application's Startup_Task using notation as follows:
Do $prefs.$showsystemfocus.$assign(kFalse)How can you tell for sure that a reference is valid? Testing for a valid reference is easy.
If Ref
; Valid reference.
Else
; Not a valid reference.
End If
The problem is if you are trying to just trap an invalid reference.
If not(Ref) will give you a problem if the reference is null or is an Unset Reference.
An interesting solution is to test the $ident property of the reference.
If not(Ref.$ident)
; NULL or Unset Reference.
End If
The only exception to the $ident test is testing a library refererence. All other references seem to work okay.
A sure fire way to set for invalid references is to always test first for the valid reference and put the invalid test in the else.
; This test will correctly trap a null or unset reference.
If Ref
Else
; NULL or Unset Reference.
OK message {The item reference is unset or null.}
End If
Trapping null, blank, or zero is a tricky thing to do cleanly in Omnis Studio.
One might expect the following If calculation to catch the 3 possibilities:
If isnull(Var)|Var=''|Var=0
but it won't work if Var=NULL
If Var=NULL, then the 2nd test, Var='', is testing NULL=''. Omnis Studio can't evaluate NULL='', and therefore it can't properly evaluate the If calculation.
Switch/Case doesn't help much either.
The difficulty with many solutions is that they may work if Var=kCharacter but fail if Var=kNumeric
(or visa versa)
Here's a bullet proof, one liner test for null, blank, or zero!
If pick(isnull(Var),Var,'')=''|pick(isnull(Var),Var,'0')='0'
OK message {IS Null, Empty, or Zero////Var = [Var]}
Else
OK message {IS NOT Null, Empty, or Zero////Var = [Var]}
End If
To avoid repeating the above If calculation statement all over your code, I recommend you add it as a method in your oFunctions object class. The following $isNullBlankZero method is included with the oFunctions object class in StudioTips. Feel free to copy it to your own library.
$isNullBlankZero method (included in oFunctions)
; Test for null, blank, or zero.
If pick(isnull(pfVariable),pfVariable,'')=''|pick(isnull(pfVariable),pfVariable,'0')='0'
Quit method kTrue
End If
Quit method kFalse
If oFunctions is instantiated using the Startup_Task variable fn, you could do the following in your code.
If fn.$isNullBlankZero(Var)
; Action to take if null.
Else
; Action to take if a value.
End If
; Use not() if you just want to do something if there is a value.
If not(fn.$isNullBlankZero(Var))
; Action to take if a value.
End If
When you upgrade your developer version of Omnis Studio to a newer version you lose all of your IDE preferences. (IDE window size and locations, toolbar settings, treelist preferences, etc.)
Your Omnis Studio preferences are stored in the omnis.cfg file which is located in the studio folder inside the Omnis Studio folder.
Your Omnis Studio session and VCS sessions are stored in the sql.df1 file which is located in the studio folder inside the Omnis Studio folder.
You simply need to copy the omnis.cfg file from your old version of Omnis Studio to the same location in your newer version of Omnis Studio.
If you have any sql.df1 file located in the studio folder to the same location in your newer version of Omnis Studio.
sessions or sessions also copy theBe sure to copy any extra external components (i.e. Third party DAMs) from your old xcomp folder to the newer version xcomp folder. You might need to download newer versions of some of the external components rather than copy them across.
As of Omnis Studio v4.2 on Mac OS X to get to the studio folder you will need to:
The serial number is also imbedded in the omnis.cfg file. If you are moving to a version of Omnis Studio that requires a new serial number you will not be able to open Omnis Studio after you copy the omnis.cfg file. To solve this, you will need to enter the new serial number in the serial.txt file located in the Omnis Studio folder.
The format for the serial.txt file is:
UN=user name (not required)
CN=company name (not required)
SN=serial number
[Plugins]
There are two ways a method can return a value to the sender.
This method uses Quit method to return the value to the sender.
$retRemoveSpaces(pVariable)
Quit method replaceall(pVariable,' ','')
This method uses a field reference parameter to pass the value back to the sender.
$removeSpaces(pfVariable)
Calculate pfVariable as replaceall(pfVariable,' ','')
Quit method kTrue
I normally use the return value to return a boolean value to indicate to the sender either: success (kTrue), or failure (kFalse) in the called method.
If you use the return value to return a real value it becomes more complicated to indicate failure to the sender. In most cases you could return null instead of a real value. The user can then use isnull(ReturnValue) to test for failure by the called method. However, if the method could return null as a valid value you have no way of testing for failure. That makes it very difficult for error handling in non-visual class methods.
The advantages of using the return value to return a real value is that you can use the method for inline calculations.
The advantages of using field reference parameters to pass values back to the sender are:
The disadvantages of using field reference parameters to pass values back to the sender are:
If you use an eval() function in your code and there is an error in your eval() how do you find the error?
You can use Test for valid calculation with #ERRTEXT. The beginning of the #ERRORTEXT will tell you the first and last character of your string which is causing the error in the eval().
#ERRTEXT might be something like
0:4:Unrecognized variable name, item name or attribute
. The 0:4 specifies that the error is with characters zero (0) to four (4) in the string.The following sample code gives you a working example:
; Calculate a text string to be evaluated. ('midx' is not a valid function.)
Calculate EvalString as 'midx(#S1,1,3)'
; Test the evalf() with 'Test for valid calculation'.
Test for valid calculation {evalf(EvalString)}
If flag false
; The #ERRTEXT will look like '0:4: ...'. The 0:4 is the first and last characters in the string causing the error.
; Parse out the first and last character positions.
Calculate ErrorTextString as #ERRTEXT
Calculate FirstChar as strtok('ErrorTextString',':')
Calculate LastChar as strtok('ErrorTextString',':')
; If the first character is zero, it will cause problems with the "mid()" function. Use pick() to set zero to one.
Calculate FirstChar as pick(FirstChar=0,FirstChar,1)
; Calculate the portion of the eval string causing the error.
Calculate EvalStringError as mid(EvalString,FirstChar,LastChar-FirstChar+1)
OK message [sys(85)] (Icon) {There is a problem with the eval string: ////'[EvalString]' ////The error is: '[EvalStringError]'}
End If
Quit method kTrue