Setfilevariable will not accept a variable as the value to be conveyed

The setfilevariable statement has the form

setfilevariable database, variable, value

I’m having great difficulty using a variable in the final parameter. I’ve tried the quoted( function and the execute statement in all sorts of combinations and I’ve tried the setfileglobal statement but nothing works. The documentation is silent on the admissibility of a variable in this parameter.

The documentation defines the first parameter as “the name of the database that contains the fileglobal variable”. I assume this means “the name of the database that will contain the new fileglobal variable value”.

Can anybody make this work?

Yes, I can.

I created a new database named “Untitled 3”, with a procedure with this code.

let x="zorg"
setfilevariable "Untitled 2","ktest",x

I already had a database named “Untitled 2”. I ran the code above, then went to “Untitled 2” and created this procedure:

message ktest

When I run this code, the message “zorg” appears! Just what I expected :slight_smile:

A variable is always allowed except in situations where a variable or field name is what is being specified, for example the field statement, or the sizeof( function … or, the second parameter of the setfilevariable statement. But the third parameter, that is a value, not a name.

Excellent! Thank you.

I have to go and cook dinner. I’ll check tomorrow on where I went wrong.

Still not working, so let me elaborate. The fileglobal variable, lvFinYear3, is evaluated by selection from a popup menu button list. A procedure is then called by clicking on another button (a rectangle object). The called procedure currently comprises no more than this:

let lvNewFile = "Income & expenditure " + lvFinYear3
openfile lvNewFile    
setfilevariable lvNewFile,"lvFinYear4",lvFinYear3

but this is the result:


The value of lvFinYear3 is recognised when opening the new database but not in the setfilevariable statement. I can re-create this in any other database.

If the value of lvFinYear3 is set with a let statement, there is no problem.

This looks similar to the bug affecting opensecret files but inserting a setactivedatabase statement doesn’t help in this case.

Your setfilevariable command is naming the wrong database. lvNewFile contains the name of the database you just opened, but lvFinYear3 belongs to the database that was active before you opened it.

Then, can you explain how this code:

let lvFinYear3 = "2018-19"
let lvNewFile = "Income & expenditure " + lvFinYear3
openfile lvNewFile
setfilevariable lvNewFile,"lvFinYear4",lvFinYear3
message lvFinYear4

produces this result:


whereas, if I define the value of * lvFinYear3* using a popup menu button, it fails?

First of all, the way you have written this code you are still specifying the newly opened database. You could have written code that does the same thing with the letfileglobal statement.

let lvFinYear3 = "2018-19"
let lvNewFile = "Income & expenditure " + lvFinYear3
openfile lvNewFile
// setfilevariable lvNewFile,"lvFinYear4",lvFinYear3
letfileglobal lvFinYear4 = lvFinYear3 // this does the same thing as the previous line
message lvFinYear4

Or, you could have used setfilevariable with "" for the database name.

setfilevariable "","lvFinYear4",lvFinYear3

In the code above, you have defined lvFinYear3 as a local variable. So it stays in scope thruout the procedure, even though the current window and current database change when lvNewFile is opened.

If you define lvFinYear3 via a popup menu button, it will not be a local variable – it will be either a fileglobal or windowglobal variable (probably fileglobal, as that is the default unless you change the form preferences). Either way, that variable will go out of scope as soon as the openfile statement runs. Now there is a different database, and a different window, so there are now different sets of fileglobal and windowglobal variables. You can’t access any of the ones associated with the previous database any more. So the error has nothing to do with setfilevariable, the error would occur if you accessed lvFinYear3 in any way. As far as the program is concerned, lvFinYear3 doesn’t exist any more.

There are two solutions to this. The first one is to copy the value into a local variable.

let tempValue = lvFinYear3
let lvNewFile = "Income & expenditure " + lvFinYear3
openfile lvNewFile
letfileglobal lvFinYear4 = tempValue
message lvFinYear4

The second method is to use the fileglobalvalue( function, which allows you to access any fileglobal variable in any open database, not just the current database.

let wasDB = info("database")    let lvNewFile = "Income & expenditure " + lvFinYear3
openfile lvNewFile
letfileglobal lvFinYear4 = fileglobalvalue(wasDB,"lvFinYear3")
message lvFinYear4

In these examples I used letfileglobal instead of setfilevariable, because as I explained before they are doing the same thing in this code. But you could also use this same technique with the setfilevariable statement.

setfilevariable "Some Other Database","Some Variable",fileglobalvalue("Another Database","Some Other Variable")

Sorry you had to spend so much time on this Jim but many thanks. Thirty years working with Panorama and I still don’t have clear handle on variables!

There’s a training video on variables that reviews the fundamentals of variables. Not sure, of course, if you would anything new, but I certainly did when i took the PanX course.

I was going to mention that training video, but Tom beat me to it (thank you for the plug!). That particular video really goes into detail about how fields and variables interact with databases and windows.

That also reminds me that I didn’t post the information about our “Back To School” 50% off sale for the training videos. To get this special deal, simply visit the Panorama X Vimeo On Demand Page, click the Buy All button, then enter the coupon code AX92SDEU at checkout (this code is valid thru Sunday, September 9th).

Good idea Tom. The videos are excellent at ‘filling in the gaps’ that the Help wizard doesn’t have room to cover.

That said, after Jim’s very lucid explanation of what was happening in my case, I went back to the wizard and found the ‘The Life Cycle of a Variable’ section of the Variables entry to be almost as complete an explanation as one could want - I commend it to anybody who has uncertainties about variables.

Here the link to the Variables help entry.

The The Life Cycle of a Variable section of this entry is good, but the video actually walks you thru exactly what happens to variables as you switch from one database to another.

If you’ve been exposed to other programming languages, the way Panorama handles the scope of a variable is different because scope is tied to visible elements of the program, databases and windows. As different windows come to the front, variables automatically go in or out of scope. There is nothing quite like that in languages like C, JavaScript, etc. If you’ve used JavaScript in the browser, it is a bit like having a separate DOM tree for each document.