Today we’re going to look at some ways single-segment button bars (SSBBs) can help produce dynamic column headings for list views and/or reports, with a goal of concentrating logic into the segment calculation and reducing schema dependencies elsewhere. This is a work in progress, rather than a finished, battle-hardened methodology. The aim is to explore possibilities and stimulate discussion.
Note: the demo files are built on top of an “empty” virtual list table. The point is not to (once again) dive into virtual list or clickable/sortable column headings, but to provide a list view we can pretend contains valid entries, while we focus on what’s going on in the layout header part.
Okay, let’s start by looking at demo #1 which is intentionally very basic. As stated above, this article is not about virtual list, but since I based the main layout on an eviscerated virtual list table, let’s take a quick look at its mortal remains via Manage Database.
Really all we care about here is that there are two repeating fields, one of type text and one of type number, each with 300 repetitions (only 37 of which will concern us here).
If we go into layout mode…
…we can see that the first column corresponds to (repetition 1 of) cell_text_r, and the remaining 36 columns correspond to reps 2–37 of cell_num_r. So each column corresponds to a unique field repetition, and in this case they proceed sequentially from 1 at the far left through 37 at the far right.
Returning to browse mode, if we click “Set/Clear Headers” a card window will appear and we can choose which months to display…
…updating this global variable in real time.
As you may have surmised, or determined via layout mode exploration, each of the labels in the header is a single-segment button bar (SSBB) object with most of its chrome stripped away. A dead giveaway is the word “calculation”. Here in demo #1, these SSBBs exist for display purposes only, and if we focus on the month headers…
…we can see that their action is “Do Nothing”, and the display calculation for all twelve is identical — except for the “v” value, which ranges from 1–12, and which ensures we display the correct corresponding value (if any) from $$heading.list.
Note that while the months will display sequentially from left to right, there’s no requirement that they be contiguous. Part of the dynamic nature of this approach is that it will adapt to circumstances, e.g.,
Okay, so much for the month headers. Things get a little more interesting with the individual column headings, “Est”, “Act” and “Pct”, which repeat for each visible month. I didn’t want to hard-code those values for four reasons: 1) to avoid the initial drudgery, 2) to avoid later drudgery if the hypothetical customer for this project changed their mind re: what labels they wanted to see there, 3) because dynamic approaches tend toward reusability, and 4) are almost always more interesting than static ones.
Cycling through three possible options (“Est”, “Act”, “Pct”) put me in mind of the Mod function, which returns just the remainder when you tell it what to divide by. Since there were three possibilities it seemed like “modding” the repetition number by 3 might be a good way to go, most likely with some sort of offset since I was starting from rep #2. When you “mod” a number by 3, there are only three possible outcomes: 0, 1 or 2. Hmmm… 0, 1, and 2 look an awful lot like JSON array address, so what would happen if, at startup, we were to populate $$subheading.array like so?
We would end up with this little array…
…which could easily be parsed out by the SSBB calculation, provided it looked something like this.
Note that all 36 of these sub-header calculations are identical except for the initial “r” declaration (which, in case it isn’t obvious, represents the corresponding field repetition number).
- Define e as Mod ( r – 1 ; 3 )
- This will return 0, 1 or 2
- Target that value in $$subheading.array
Note also that we are using the Div function to determine whether to show or hide the column label.
- Define v as the number of months in $$heading.list
- Define o as r + 1
- Div o by 3 which will return some number between 1 and 12
- If the result is greater than v, display nothing
- Otherwise display “Est”, “Act” or “Pct”
In this demo we are going to address a major shortcoming in demo 1: if we want to revise the SSBB calculation syntax we are going to have to revisit those 36 SSBBs and re-do each one of them. Wouldn’t it be nice if there were an easier way?
Actually to remedy this shortcoming we are going to have to re-do the above-mentioned 36 SSBBs, but this will be the final time, because we’re going to redefine them from this…
…to this (bearing in mind that the “r” value will continue to be column specific):
In other words, we’re abstracting the calculation logic out of the SSBB and into one global variable that all 36 SSBBs will reference.
That variable is populated via the startup script and looks like this:
From now on, if we want to make any changes to the calculation syntax for those 36 SSBBs, we will only need to do it in one place… which is good because in demo 3 we’re going to make some significant revisions to that syntax.
But before we do, let’s look at another improvement in demo 2. Remember how in demo 1 the SSBBs don’t perform actions? Now in this demo, they all perform the same script, but without requiring a script parameter. Instead we tap into the “r” value that we already hard-coded into the SSBB calculation syntax.
The script doesn’t do much, just reports the column number of the SSBB being clicked, with help from the $$button variable declared in $$subhead.definition… which conveniently is updated when the user clicks the SSBB.
From a user standpoint, what’s interesting about demo 3 is that when you click on a column heading you get to see a sort indicator, and clicking that same column a second time toggles the indicator in the opposite direction.
(We don’t actually sort in this demo; as mentioned at the outset, clickable/sortable column labels have been covered many times on this site, most recently in Virtual List Reporting, part 4.)
There are several interesting things going on from a developer standpoint…
1. This demo is virtually identical to demo 2. No changes were made at the layout level, only at the scripting level.
2. The sort indicators are not separate objects; they are Unicode characters included as part of $$subhead.definition (thank you Nathan Allen at Codence for opening my eyes up to this possibility). Here’s that expanded definition:
(To be clear, the unwieldy code you see above is not what makes this technique cool. What makes it cool is how easily you can swap in your own code.)
3. The same script is attached to the SSBBs as in demo 2, but it has been renamed to “column sort” and expanded like so:
4. There are no script parameters, no Hide Object calcs, no conditional formatting, no named objects, no custom functions, plug-ins or web viewers, and the sort indicators do not require separate layout objects.
As stated at the outset, all of this is very much at the proof-of-concept stage. Currently the assumption is that you will only have one virtual list window displayed at a time (i.e., the variables for the column headings are scoped to the table, not to the layout or window). The technique can be extended so that the column headings and sort indicators are window-scoped (as per Virtual List Reporting , part 4), thereby allowing multiple reports with different column labels and/or sort indicator states to be displayed simultaneously, but that will be left as an exercise for the reader.