Custom Function in Pan X

Hello Everybody,

I’m sure this will be easily answered, but I’m stumped.

The Pan X help for the statement:

registercustomfunction

describes how to write a custom function. So far, so good. But it says a good place to define a custom function is to put it in a procedure, inside a custom statement library, inside the

~/Application Support/PanoramaX/Libraries folder

Great. But I have no such folder on my Macintosh. Even a Spotlight search does not show any such folder. I found an “Application Support” folder, but there is nothing inside that folder similar to what is above.

Please keep in mind many of us are not programmers. We can write fairly sophisticated macros using clever algorithms, often with help from the forum. But the intricacies of navigating the penetralia of the Mac are beyond us, and frankly, of little interest. I’m sure there is a hidden folder, somewhere, with that name.

So, where do I write a custom function that will do what it did in Pan 6?

Regards,
Vic

The Application Support folder is inside your user Library:

~/Library/Application Support/PanoramaX/Libraries folder

Chances are these files are hidden on your system unless you intentionally turned them on. All is not lost since you can turn them on fairly easily. In the Finder’s left hand sidebar, select your hard drive then use Command-Shift-.(period) to toggle the hidden files on and off. You will find the correct Library file on your startup drive in the User/youraccount/Library folder where youraccount is the name of the account you log in as.

In Finder, hold down the Option key and choose Library from the Go menu.

To All Who Responded -

KJM: ??

Gary: I did as you suggested, but no luck Command-Shift-<(period) doesn’t do anything. In my Users:account name folder, there isn’t a Library folder.

michael: That works - after a fashion. That technique does show a Library folder which was hidden, and which has an Application Support folder within. But within that folder there is no PanoramaX folder. There IS a Panorama folder, but nothing about an initializefunction file.

Close to giving up.

Vic

Yes there is, but by default it is invisible.

I did a simple google search for macos show library folder and found this handy page – there are many others.

Yes, so you already got it open, but you still may find the link above useful.

Just create it same as you would create any other folder, and then create a Libraries folder inside of it. No magic required.

Hello Jim,

So, the user has to first CREATE a “PanoramaX” folder inside that invisible folder. I would have thought the program would automatically do that itself. And then I create another “Libraries” folder inside that “PanoramaX” folder. And then what? Do I add a new database inside THAT folder, create a procedure called .initializeFunctions, and put the custom function inside that procedure? That’s a lot of creating.

If that’s what is necessary, I can follow and do that. But Jim, couldn’t some more elaboration have been added to the Help page for the registercustomfunction? Is this something that the average user would be likely to know? Is he even likely to know how to show an invisible folder? And if the folder is so important, why is it invisible in the first place? Is there any risk in showing it or modifying it?

I wonder if custom functions is a bridge too far.

Vic

First of all, custom functions aren’t for average users. This is undoubtably an advanced feature, and one that I don’t think more than a handful of Panorama 6 users ever took advantage of.

Secondly, you can put your registercustomfunction statements in ANY procedure. They will go into effect when the procedure is run. So you might find it handy to put it in the .Initialize procedure, so that it will run automatically when a database is run. You could even split up your registercustomfunction statements into different procedures, I can’t think of a reason to do that, but you could if you wanted to. Panorama doesn’t care, as long as the procedure gets run somehow.

By putting the registercustomfunction statements into a library, you can get it to run automatically when Panorama launches, just as if the custom function was built into Panorama itself. So that’s convenient, especially if you have lots of different databases you use and you’d like your custom functions to be available in all of them without having to add the functions to each database individually. But if you just have one database or a small set you use, it’s probably simpler to add the custom functions to one of those. Or just don’t use custom functions – we’ve given you hundreds of already built functions you can use.

Because – Apple. It didn’t used to be invisible, but a few releases ago for some reason they made it invisible. I immediately made it visible again on my computer, and so do a lot of other people.

Well, I wouldn’t recommend randomly deleting stuff in the /Library folder, but that goes for any folder. If you did, some apps might break, and some applications even store their data in there. But if you don’t delete or rename stuff that you don’t know what it is, you’ll be fine.

It sounds like you might be happier putting your custom function setup in one (or more) of your databases instead of into the /Library folder, and that’s fine.

That sounds like good advice, Jim. That’s what I will do.

Best regards,
Vic

Hello Jim,

Allow me one last point.

I did as you suggested, and it worked (of course). With one minor caveat.

Adding the registercustomfunction statement at the beginning of one of the macros did NOT allow me to choose and “RUN” the macro, because Pan X still complained about an unknown function. I had to comment out the code lines referring to the function, then run the macro (with ridiculous results) so that the register statement was executed, and then un-comment the code lines referring to the function. Then all was well - with THAT macro.

But all the other macros in that database which referred to the function also were blocked from running. Apparently, Pan X remembered there was an unknown function in those macros, and blocked their execution.

But Jim, that’s a lot to go through. And in that database, there are over 5 macros with that function, repeated many times.

Do you think an improvement would be to force Pan X to re-analyze a macro, when an unknown function is encountered, and remove the block if the function is now recognized? That will save a user from manually opening/closing all other macros with that function reference.

Now, take the rest of Sunday off.

Best regards,
Vic

You can’t use the custom function in the same procedure that defines the custom function.

I would suggest that you define the custom function in the .Initialize procedure for the database, then only use the custom functions in other procedures.

Jim,

I think your creation is smarter than us. Or me, at any rate.

As a test, I wrote a 3-line procedure with a simple custom function, put the register statement as the first line, and ran the procedure. (I first commented out the custom function just to get the macro to run and the register statement to activate, then un-commented the custom function). The procedure ran properly as expected, giving the correct value of the function.

I then commented OUT the register statement, saved the database, and quit Pan X. I then re-opened the database. The custom function should not exist yet, right? But when I ran the simple procedure, with the commented out register statement, the function worked! I didn’t need to run the register statement again.

Pan X must have remembered the custom function from before, and kept the function active. As long as I didn’t “Check” the procedure in the macro window, that function remains available. Opening the procedure window and “Checking” the code destroys this, and the custom function disappears.

So it looks like once created, a custom function remains active. Just don’t “Check” the code again.

Vic

As long as you don’t click the box to check the procedure, or make any editorial changes to the procedure, it won’t try to recompile. When a custom function is compiled, it is simply replaced by the formula that defines it. Once it is compiled, the statement doesn’t contain any custom functions, so it doesn’t matter if the custom function exists or not… until you try to edit that procedure, and it needs to compile again.

Dave’s explanation is correct, and it didn’t occur to me. You would think that since I wrote this code, I would have a better shot at knowing what is going on than Dave, but not in this case.

One reason it didn’t occur to me is that I’m pretty sure that Panorama 6 did not work this way. In Panorama 6, formulas are kept in text format until they are actually used. But Panorama X pre-compiles the formulas when it can (this helps the formulas run a bit faster). And Dave is correct, when a formula is pre-compiled any custom functions in the formula are converted into basic functions and operators.

I wouldn’t rely on this behavior. First of all, of course, if you make any changes to the code, the custom function won’t work. Also, there are some situations where formulas cannot be pre-compiled, for example if a formula is inside an execute statement, or an arraybuild( or superlookup( function – basically any situation where the formula has to be quoted. So I would suggest putting the custom function definitions in an .Initialize procedure as I mentioned earlier, so that they will always be available within that database.

Will do. But isn’t the function also available for any other database as well, even if you close the original database? The Help file indicates that will be the case, although I haven’t tried it yet.

Vic

Yes, it will be available until you quit Panorama X. The only problem would be if you opened the other database before opening the database that contains the custom function definition. Depending on how you’ve set up your databases, that may never be an issue, but you should be aware of it.

I have a custom statements database in my Application Support/PanoramaX/Libraries folder, and I have put my custom function in there, as well as my custom statements. But the process makes me wonder: Does PanoramaX open any file in that folder when it starts up, or does the file have to have a specific name?

Yes, it opens any Panorama X database in that folder when it starts up – but it opens it as a library file, not as a regular database. So no windows will open, and it calls .InitializeLibrary instead of .Iintialize. Also, the database will not appear in the Recent menu.

Mine is showing up in Recents:

How about some simple code that will place a copy of your current db with custom functions in the proper place. This will work even if the PanoramaX and Libraries folders do not exist since they will be created on execution. This code uses the makefolder statement to make sure the folders exist and uses the saveas statement to save the current db to the PanoramaX/Libraries folder under whatever name you give it (I have given it the name “TestCustomFunctions” here).

makefolder commonpath("Library")+{/Application Support/PanoramaX/Libraries}
saveas commonpath("Library")+{/Application Support/PanoramaX/Libraries/TestCustomFunctions}

This will automatically adjust the path to the current user’s Library folder. If the folders already exist it will do nothing and the saveas witll either copy the file or update an existing file if there already is one with that name in the folder. This will work whether the Library folder is currently hidden or not.