Objectinfo "procedures" Not Working

Hello Everybody,

The objectinfo function for procedures is not returning the correct result.

The following code:

temp = objectinfo("name", 1, "Form1, "DB")

correctly returns the name of a Text Display object. But the following step

temp = objectinfo("procedure",1,"Form1,"DB")

returns empty text. The object does have some text in the “Procedures” tab in the form window, so there should be something in the temp variable.

Am I missing something?


Well, both of those code samples are missing a quote, but I suspect that is just a typo you made here in the forum.

Mostly likely object 1 isn’t the object you actually think it is. The procedure option definitely works. A good way to double check this is to right click on the object and check the blueprint (internally, by the way, the blueprint dialog uses objectinfo("procedure" to find out what the code is).

Specifying a hard coded object number is almost never going to be a good idea. The object number can change as the form is edited. Better to give the object a name (which you apparently have already done) and use that name (and make sure the name is unique). Usually the only time I would ever use a number with this function is if I got the number with the info(“clickedobjectid”) function.

Hello Jim,

I was pretty sure you would say the function worked. It didn’t seem like something you would have missed - it’s too basic.

But there is a problem with the function. My actual code is below. You see that I am cycling through ALL objects on the form. An outer loop (the k loop) cycles through each form. I do not show that outer loop here.

There are 3 objects on the first form. When the code below runs, the message window appears a total of 6 times, alternating between “No Proc”, and the correct object name.

The entry in each of the Procedure windows is simply “//test entry”, without the quotes, to help me set up and debug the code. But the point is, there IS an entry in the procedure window. Does the fact that the procedure is only a comment invalidate the function?

loop    // i loop
        temp = objectinfo("procedure",i,
    message ?(temp = "", "No Proc", temp)

        tempname = objectinfo("name",i,
    message ?(tempname = "", "No Name", tempname)

        If temp ≠ ""
            Field «Macro Text»
            CELL temp
            Field «Called By»
            CELL "Form " + {"} + array(t2,k,¶) +{", Object Name = } +
        i = i + 1
        stoploopif i > n


It took some sleuthing to reproduce, but you have discovered a bug. Most options of the objectinfo( function don’t work if you specify an alternate database, including the procedure option. The name option, however, does work. I’ve written up a bug report, but for now, there is no way to access this information for a form that is not in the currently active database. (It will work, however, for different forms in the current database.)

It has nothing to do with getting the procedure text, but as an aside I am wondering why you have picked such a complicated way to do assignments, using the field and cell statements instead of just an assignment. Why not just use basic assignments like this?

«Macro Text» = temp
«Called By» = "Form "+{"}+array(t2,k,cr())+{", Object Name = }+tempname

But of course if you think using field and cell is more clear they will certainly work, and this suggestion doesn’t help your primary problem.

After I sent the message above I couldn’t sleep and this problem kept turning in my head, it didn’t sit quite right. And it turns out, the bug is not what I said. It is perfectly fine to get the procedure code or any object property from an object in any open database, not just the current database. What you cannot do is access these properties from the data sheet, even from a form in the current database. You have to open a form view to use most of the options of the objectinfo( function. I think this may already be in the bug database, since it affects blueprints. I’m not sure if this can really be fixed given how Panorama’s form code works – I may just have to amend the documentation to note this restriction.

Ok, now I can sleep (I hope).

Because I am not as smart as you?

Actually, the REAL code does use the assignment technique. But when writing or debugging code, I use other methods because I use a separate database with text display fields to allow me to look at intermediate results. My real “debugging” code was not the one I actually quoted.

But from what you said in your last reply, it looks like I can proceed with my macro, but I have to first OPEN the form before accessing the objectinfo function. That’s not too difficult to do. But it will cause annoying window flashing for the final macro. That’s OK during debugging/writing, but for the final code, can the form window be opened SECRETLY? I always have problems with SECRET windows. I don’t like them, and they don’t like me!!!

I hope you slept well, Jim. And thanks for the quick response.


You could possibly have the form open in the background and use magicwindow or magicformwindow to get the objectinfo( data to avoid flashing.

Hello Gary,

For my case, with the code cycling through all forms in the database, the magicwindow statement wouldn’t help. In each loop, a new form window will have to open, and then close before opening the next form. No telling how many forms a database has.

Can form windows be SECRET? Will the objectinfo( work with a SECRET window? Later today, or tomorrow, I will give it a try. But I really dislike SECRET windows.

I was hoping with PanX Jim would make the NOSHOW command a real noshow, and freeze the screen. That would be the ideal solution. Then, he would be able to figure out how to reinstate color to the datasheet :grinning:.


I don’t think there is any such thing as a secret window. When the the file is made secret all the windows are closed - not secret. The old window “DatabaseName:Secret” routine simply made an already secret database the active database and has now been replaced by the setactivedatabase “DatabaseName” statement. Again, no secret windows are actually created.

I think your choices are rather limited in this regard. Even opening a form off screen or as a tiny window size (1,1,1,1) will cause flashing as the your main form highlighting flashes when active and not active.

Hmm, maybe there is another way to get this info for forms that are not visible but in an already open database (wether opened normally or secretly). Check out the formblueprint statement that will return the blueprint of the entire form including all the individual objects.The hardest part will be processing out the information you need from the full blueprint. Here is a partial return of the form objects section from a simple blueprint returned from an open but secret file:



newformobject “PopupButtonObject”,
“rectangle”,rectanglesize(88, 70, 26, 100),
“TextSize”,“14 px”,
“$BorderRightMargin”,“0 px”,
“Opacity”,“100 %”,
“$BorderLeftMargin”,“0 px”,
“$PopupButtonStyle”,“Push Button”,
“$BorderBottomMargin”,“0 px”,
“LineWidth”,“1 px”,
“$BorderTopMargin”,“0 px”



Sorry, you must have an open visible form window as the active window when you run this function. The formblueprint statement actually uses the objectinfo( function to do it’s work, so that doesn’t change the situation at all.

However, there is no reason that you can’t do all of the assignments, adding records, etc. in a form window. No reason to flip back and forth between windows or have any flashing.

If you want further advice for your application perhaps you could tell us what the application is. Clearly this is not going to be for operation of a normal database, it looks like maybe it is some sort of debugging aid for you? That sounds great, but without understanding what your goal is it’s hard to assist. Why do you want to have a data sheet that displays the code inside objects? What are you going to do with that once you’re finished?

Yes, my test was with a standard form active and not the datasheet. :flushed:

I have a Pan6 database file, which works perfectly. I am trying to convert it to PanX. It does things which are very valuable to me.

Many, in fact most of my databases open and close other databases to utilize common macros as FARCALL subroutines. For example, subroutines that solve polynomial equations, or do other more abstract calculations, need only be written and debugged once. And if they need to be changed, I need change them only once in their original file.

But with this approach, how do I know which files depend on which other files?

The database I wrote does the following:

1- It allows me to pick a macro from a list of ALL macros, in every database I want to follow, and shows me which macros and which databases “CALL” that macro. If a macro is not “CALLED” or “FARCALLED” by any other macro, it does not appear in the list.

2- It allows me to pick a macro from a list and shows me what other macros, and which databases, the picked macro itself CALLS.

3- It tells me how any macro is activated - by menu, or by a button on a form. And tells me what button it is, what form it is, and what database it is.

4- It allow me to search all databases macros for any text phrase, and selects all macros with that phrase, shows those macros in a separate text display window (a dropdown menu allows you to pick one), and highlights the selected phrase in bold green to make it easy to spot the phrase.

It took quite an effort to write that Pan6 file many years ago, but I have used it extensively. It basically serves to show connections between all databases I want to follow. A separate database lists those files. I “Update” the file periodically - with a macro. It takes about 30 seconds to run the update.

I’ll bet the experts on this forum could have written this file more easily, and with more elegance. But they wouldn’t have had as much fun as I did when writing it. Or pleasure in watching it work.

Now, to get the darn thing to run on PanX.


The Open View dialog in the View menu can help with this sort of question. Just make sure the All Databases and Full Source options are enabled. See Searching Full Source and Expanding the Scope on the Open View help page.

Still, I can see where the cross reference database you have built could be useful. You’ll just have to make sure that you have a form window open when you run the code that updates the cross reference information. I would assume that you will only do that occasionally, so that shouldn’t be a big problem.

I’ll also note that building this type of homegrown cross reference database would be impossible in Panorama 6, since the objectinfo( function in Panorama 6 had no way to find out what subroutine was being called, and could not access objects in other databases or forms.

Not so, Jim.

I wrote this database many years ago, in Pan6. It works PERFECTLY!

To make it work, I have to follow a formatting plan with all my macros (which is probably a good idea anyway). For the database to work correctly:

The above is in an “Instruction” form in the database to prompt my memory. And critically, a separate macro in the database does an internal check of all macros, and flags (selects) all macros that DO NOT follow these format rules. It doesn’t change any macro - it merely flags it and highlights the omission. If the omission is not changed in the offending database, the only effect is that that particular cross-link will not work. Not terribly important. But I always change the format in the macro to comply. After all, why not?

But a lot of the commands in the macros of this Pan6 file are not recognized by PanX, so I am in the process of modifying those macros. And PanX allows ANY form object to have a procedure, which requires a re-think of how to handle that.

I figure updating this database is a good way for me to learn PanX.

As a July 4th challenge I wrote a procedure that will scan all of the objects in all forms in a database and record the object id, class (object type), name and code. This assumes the database has 5 fields: Form, Object (Integer), Class, Name and Code. I tested this code and it does work very well.

let scanBase = "Untitled" // substitute the name of the open database you want to scan

looparray dbinfo("Forms",scanBase),cr(),formName
    let objectNumber = 1
        let oClass = catcherror("",objectinfo("class",objectNumber,formName,scanBase))
        stoploopif oClass=""
        if Form<>""
        Form = formName
        Object = str(objectNumber)
        Class = oClass
        Name = objectinfo("name",objectNumber,formName,scanBase)
        Code = objectinfo("procedure",objectNumber,formName,scanBase)
        objectNumber = objectNumber+1

To use this you should call this code from a button in a form – as discussed earlier in this thread, it won’t work if you try to use it in the data sheet. This code will run with no “flashing”, it doesn’t need to open (or close) the forms being scanned.

The code works perfectly — as long as you keep the calling button in a form of the analyzing database.

I made some tests using a button in a form of the analyzed database; it worked the first time, but when I tried it again, I got an error that the field “Form” did not exist, and the deleteall statement deleted the data in my analyzed database. I had to recover the database from a backup.

Hello Jim,

Wow. What a professional, efficient, and compact procedure. It makes my attempt seem so amateurish. Well actually, I am an amateur programmer.

And, as a July 4 challenge, you completed what I had been working on over a week. You really know how to hurt a guy.

Next week, I will try to get back to my project using your procedure to load in all the database macros. In the next section of my full macro, a series of tagarray( functions, array filter statements, and text funnel manipulations do the heavy lifting to establish the connections between macros and between databases. I hope the procedure I wrote for Pan6 doesn’t require too many modifications to work in PanX.

You would probably finish the effort during a coffee break.

Best regards,

I tried Jim’s code out of curiosity. It works as expected except that it does not retrieve the procedure code. No assignment is made to the Code field with the formula objectinfo(“procedure”,objectNumber,formName,scanBase), even though it correctly retrieves and assigns the name in the step before this one. If I put this formula for the Code into formula workshop, and substitute values for the variables where needed, the procedure code is correctly displayed!
I cannot get a procedure to retrieve and assign the code.

Kurt, are you sure you got the procedure code when you tested it?

Hello Jim and CooperT,

I just tried out your code, Jim, and I had the same experience as CooperT. The object “Name” was exported, but not the Procedure.