Openform statement

I am looking for some information about the openform statement.

I am using the basic openform statement to ensure that when I run a
specific procedure some or all of the code is focused on one particular
form and its objects. This worked very well, so I started playing around
with the listed options that can be applied to the openform statement.
In my case, none of the options that I tried worked, and I see no
changes in the form window. I have also tried this out with a separate
procedure that only contains the openform statement and that statement
is directed to a blank form window. Again, I saw no difference.

The options that I have tried were “NoButtons”, “NoIcon”, and
“TitleBar”. Here are a couple of examples of the statements that I
tried.

openform "Form_A", "NoButtons","yes"
openform "Form_Display Separate Selection","noicon","yes"

Has anyone else experienced this?

These options don’t affect a form that is already open, they only work when the form is first opened. Some, but not all, of these options can be changed later with the setwindowoptions statement.

The options you are interested in, nobuttons, noicon, and titlebar cannot be changed later, they can only be set when the window is first opened.

You can check out the magicformwindow and magicwindow statements to see if they fill the bill for your needs. They both will eliminate the need of making the wanted form the front most window.


Jim, thank you for clearing that up. I played around again with using the options to the openform statement, and I now understand how they work.

Gary, thank you for your suggestions. I checked out both statements, and
I will keep them in mind for future work. Neither of them appear to be
effective in this situation.

I have a procedure that edits the Text Editor objects in a form. The
procedure asks for some data (first name and last name), selects the
appropriate records in the Data Sheet, and then puts information from a
selected field into the TEOs. I am doing it this way because I want the
selected data to continue to be displayed without changing while I edit
the Data Sheet. The only glitch is that if focus is on the Data Sheet
when I run the procedure, the procedure fails when it trys to edit the
TDOs, because the TDOs are not open to editing. Using the openform
statement solves this problem.

Here is a small section of the procedure that works because the openform
statement is there:

openform "Form_Display Separate Selection"
for i, 1, 20
    objectaction i, “open”
    objectaction i, "SetSelection",0,32768
    objectaction i, "InsertText", ""
    objectaction i, “close”
    changeobject i, "$TextEditorBorderStyle", "None"
endloop

So are these Text Editor objects linked to fileglobal variables? If so, I would suggest that you just set these variable values directly, then use the showvariables statement to display them. Also, that way you could use Text Display objects instead of Text Editors if you wanted to. This would make for much cleaner code. Also, you would not need to bring the form window forward.

Jim, the TEOs that I am editing are not linked to any variables other
than two local variables that am using for them. I am using local p_1
through p_20 in the Data: section of the Text Editor Options, one
variable for each of the 20 objects. In the procedure, each p_ variable
is set equal to the value of one of the values in the P field of the
Data Sheet. I am also using the local values of the variable i from a
for loop as names for each TEO so they can be indexed inside a case
statement.

I will look into the showvariables statement. It is one of many that I
am not familiar with yet.

I have used Text Display objects here and there, so I am not as familiar
with them as with TEOs. I considered them briefly when I was first
setting this procedure up, but I was not sure that they would be
helpful. Basically, what I want do with this procedure is to update a
window in the form only when I make a selection using a first name and
last name pair. The rest of the form is mostly populated with other TEOs
that I use to update other fields in both old and new records. So
editing is something I have been thinking about a lot recently. I will
spend more time investigating TDOs to see if they can improve this
particular part of the form.

I assume you mean that the variables are named p_1, p_2, etc. These are not local variables, they are fileglobal variables. Local variables are available only inside a procedure, they disappear as soon as the procedure ends and they cannot be displayed or edited in a form. See The Life Cycle of a Variable in the Variables help page.

So, in a procedure you could have code like this:

letfileglobal p_1 = "Alpha"
letfileglobal p_2 = "Beta"
letfileglobal p_3 = "Gamma"
showvariables p_1,p_2,p_3

These variables could be displayed in a form using either a Text Editor or Text Display object.

Sorry, I’m still not following what you want to do, but whatever that is, my point is that it’s going to be much easier to modify variables directly in code rather than trying to jam the value in thru objectaction. So, instead of

openform "Some Form"
objectaction "1","open"
objectaction "1","setselection",0,32768
objectaction "1","inserttext",""
objectaction "1","close"

you could perform the same action with:

letfileglobal p_1 = ""
showvariables

Or to zap out your entire group from 1 to 20, as your example code does, do this

for i,1, 20
setfileglobal “”,“p_”+i,""
endloop
showvariables p_1,p_2,p_3, … ,p_20

Jim, I am in the process of familiarizing myself with the suggestions
you made.

Since the p_i series of variables (from 1 to 20) that I was using worked
in the standalone procedure, I just assumed that they worked without
being declared because they were local. But in other situations, I have
had to declare local variables. I think what was happening here was that
these variables worked without declaration in the procedure because they
had already been placed in separate TEOs in the Data: section of the
Text Editor Options. If that is the case, then I did not recognize that
I was delaring a fileglobal variable in the process.

I also have a group of TEOs set up to receive dates when separate
buttons are clicked. The date that is used is stored in a sepatate TEO.
Its button contains the declaration of variables used by the other
buttons, and the showvariables statement is used in the code of the
different buttons, but each showvariables statement only takes one
variable. And any previously entered date is overwritten without the
need for separate editing code.

I can see now, if I can get it to work, that your approach would make
unnecessary the objectaction code that I have in this procedure. It
would also do away with the long case statement that I am now using. I
think everything should fit into one small For loop.

I am having some difficulty using the For loop that you suggested. I
need to set each p_i variable equal to a different value from the same
Field. I found that I needed to use double chevrons around the variable
to avoid errors in the subsequent statements. Adding double chevrons was
the only thing that worked to get the code to run, but I am not sure if
it is a functional solution. This is where I am now with this For loop:

for i, 1, 3
	setfileglobal "","p_"+i, ""
	letfileglobal «"p_" + i» = P
	message «"p_" + i»
	showvariables «"p_" + i»
 	downrecord 
endloop

Message «“p_” + i» gives the correct value of P. But I am not sure that
showvariables «“p_” + i» is making a connection to the appropriate TEO
since the TEOs remain blank. The TEOs are also blank if showvariables
p_1, p_2, p_3 is used outside the For loop. Currently I am stuck. Is
there a different way to handle the results of the setfileglobal
statement? Or is using double chevrons incorrect?

What you are doing there is declaring, and using a variable whose name includes the quotes, the + sign, and the letter i. You are not using variables with names that end in a number, other than to set them to “”.
Try changing that to

for i, 1, 3
	letfileglobal "p_" + i = P
	message datavalue("p_" + i)
 	downrecord 
endloop
showpage

Dave, I tried using the For loop without double chevrons, with and
without using the setfileglobal statement before it. Not using double
chevrons in the letfileglobal statement results in a syntax error. If
double chevrons are used in the letfileglobal statement, but not in the
message datavalue( statement, datavalue( is blank. If double chevrons
are used in both the letfileglobal and message datavalue( statements,
the correct value of P is shown for each value of i. The value of P does
not appear in the TEOs when showvariables «“p_” + i» is used inside the
For loop, or when showvariables p_1, p_2, p_3 is used outside the For
loop. The statement showvariables “p_” + i, without double chevrons,
also causes a syntax error.

My mistake. I didn’t check the syntax of letfileglobal. It doesn’t allow you to calculate the variable name. You will need to declare those variables explicitly, one by one, and not in a loop, or use execute to calculate the statement.

The chevrons are saying that everything within them is part of the literal file name. Operators, spaces, and so on are just characters in the name, and have no other special meaning.

Ken, these two lines in your code:

	setfileglobal "","p_"+i, ""
	letfileglobal «"p_" + i» = P

are creating TWO separate values. Let me explain in detail.

Let’s assume that i currently contains 1. Then the first line of code,

	setfileglobal "","p_"+i, ""

will create a variable named

p_1

and that variable will contain empty text.

The second line of code,

	letfileglobal «"p_" + i» = P

will create a variable named

"p_"+i

Yes, that is the NAME of the variable. This oddly named variable will contain whatever value was in P.

The letfileglobal statement does NOT ALLOW you to calculate the name of the variable. If you specify a formula, then that formula will be actual variable name. I’m sure you were thinking that it would calculate the formula and use the result of that calculation as the name, but it does not do that.

So what if you want to calculate the name using a formula? That is just what the setfileglobal statement is designed to do! That’s why I used it. So you don’t want to use both the setfileglobal statement AND the letfileglobal statment, just one or the other. So you just want this statement:

setfileglobal "","p_"+i,P

Like letfileglobal, the message statement does not allow you to calculate the name of a variable. But there is a function that allows that, datavalue(. As Dave described, you could use this with the message statement, like this:

message datavalue("p_"+i)

In this case since we know that it is a fileglobal variable, you could also use the fileglobalvalue( function, like this:

message fileglobalvalue("p_"+i)

The showvariables statement ALSO does not allow the variable name to be calculated. There is no alternate statement like setfileglobal that performs the same function. But, there is a general purpose fallback that you can always use in situations like this – the execute statement. This statement allows you to construct a piece of code on the fly, then run it immediately. Here’s how in this case:

execute "showvariables p_"+i

When you run it, this will create the temporary code showvariables p_1 and then immediately run that code.

So here is your complete loop:

for i, 1, 3
    setfileglobal "","p_"+i,P
    message datavalue("p_"+i)  // could also use fileglovalvalue(
    execute "showvariables p_"+i
    downrecord
endloop

Ken, if you don’t already have it, I would HIGHLY recommend buying or renting the “Fields & Variables” video from the Panorama X Intensive training course, which covers much of this material in greater detail, with diagrams and examples. You might also want to watch the “Formula” session. (Of course, I would strongly recommend the entire course!)

https://www.vimeo.com/160498958

Yes, exactly, putting a variable in a Text Editor object, or any editable object (checkbox, radio button, popup menu, etc.) automatically declares that as a fileglobal variable. If it doesn’t already exist, that variable is created automatically when the form opens, without any code at all.

Jim and Dave, with your assistance I have finally gotten my head around
this concept. This procedure now is 69 lines of code lighter due to the
elimination of a For loop and a Case statement. Even though I mostly
understand this group of statements and functions, I am sure I will be
referring to your instructions in the future, just as I often often
reread the Help page covering the Date functions.

I will be making adjustments to this procedure as I extend it to cover
more fields. Here is the code that I came up with so far. I only left
out 10 other lines of code:

for i, 1, 20    
	if i > numOfRecords
    	setfileglobal "","p_"+i,""
    	changeobject i, "$TextEditorBorderStyle", "None"         
	else
    	setfileglobal "","p_"+i,P
    	execute "showvariables p_"+i
    	changeobject i, "$TextEditorBorderStyle", "Bezel"
	endif
	downrecord
endloop

I also plan to view the videos that you recommended. Thank you for all of
the help.

Not quite. I believe those variables are automatically declared, but that their type is determined by the Variables pop-up on the parent Form’s Form Options Property tab, which offers: Global, FileGlobal or WindowGlobal variable types. Mostly you’d want FileGlobal there, but if you intended to clone that form you probably would want WindowGlobal.

That’s true of course, and I considered putting that in there, but it seemed like the post was long and complicated enough already. The default is fileglobal so unless you knew about this option to change it, that is what you would get.