Registercustomfunction statement allows lower-case and numeric characters in its name

The registercustomfunction statement Help file entry states that “the name of the custom function must be all uppercase letters (no numbers or punctuation)”. I’ve created a custom function called stringcount.45( and it works perfectly.

I’m not complaining and I don’t see it as a bug - I just find it interesting.

Can I continue to create lower-case named custom functions or is there a reason to enforce upper-case names?

I checked the source and Panorama internally converts the name to all upper case. So you can use upper or lower case, whatever you want. What you cannot do is create different functions with different cases. For example, these three names all belong to the same function.


In other words, function names are not case sensitive, and it really doesn’t matter if you use upper or lower case when you define it. (This of course goes for Panorama’s built in functions as well, so you can use str(, Str( and STR( interchangably.

As for other characters, the function name must begin with a letter (A thru Z). After that, you can use letters, underscores, periods, or the omega symbol. Nothing else will work. And personally I would avoid periods and omega symbols, and even numbers for that matter, though Panorama does have some built-in custom functions with numbers, including time24(, os9(, tc24to30(, tc30to24(, mactoutf8(, and utf8tomac(.

I’ve filed a bug report on this:

FYI, here is a regular expression that will be true for valid custom function names:


This is a more precise way of saying “the function name must begin with a letter (A thru Z). After that, you can use letters, numbers, underscores, periods, or the omega symbol. You can optionally add a ( at the end.”

The RegisterCustomFunction statement now uses this regex to validate any function names you pass it.

This implies only upper-case but lower-case works (or does it not now?).

My limited knowledge of Reg Ex tells me that ^[A-Z} includes lower case. Is that correct?

If Jim is using regexarray( it will accept a leading character that is either upper or lower case. If, however, he is using regexarrayexact( it will only accept an upper case alpha character. If the filter was ^[A-z] instead of ^[A-Z] it would take either upper or lower case even with regexarrayexact(. Note that the ^ character indicates match at the beginning of the text line. (This also all applies to regexmatch & regexmatchexact as well.)

Gary’s got the right idea, but this code happens to be Objective-C code, so it’s not actually using either of these functions. However, I am using the case-insensitive option when evaluating the regular expression, so [A-Z] will match both upper and lower case. I should have mentioned this. Also, in this case regexarray( isn’t what I would use if this was Panorama code, I’d be using the regexmatch operator in this application, like this:

functionname regexmatch "^[A-Z][A-Z0-9_.Ω]*[(]*$"

For educational purposes, let me break down the components of this regular expression. Here’s the expression without the quotes.


It starts with


This means that the match must start with the first character. Otherwise you could have all sorts of junk at the beginning.


This means the first character of the match must be a letter. Since I’m using a case insensitive regex either upper or lower case will work. If I was using the case sensitive options (which Panorama calls exact) then I could still match upper and lower case by using [A-Za-z] instead. Gary suggested using [A-z] which would work, but would also match a few additional characters: `[, , ], ^, _, and ``.


This means the next character can be a letter, number, underscore, period or omega. The * on the end means that this match can occur 0 or more times. So it’s ok if there are no additional characters, or one, or twenty.


This means that can be a ( on the end, but it is optional (0 or more times). So this means you could define a function name of abc(((. As it turns out, Panorama removes all of the ( characters, so it doesn’t matter if you add extra ones, the name would still be abc.


This means the last character of the pattern must match the last character of the matched text. In other words, there can’t be any extra text on the end. Because of the $, names like this won’t work.


That’s it! Writing explicit code to test if text matched all of these criteria would be a lot more difficult.