ShowHide
Holds the list of variables one worksheet layer offers the user, and the visible or hidden choice for each of them. The list is built from the dictionary. EntryCount, FieldKey, HeaderText, IsHidden, PositionIndex, ControlType and AuthoredVertical read one entry, IndexOf and HasField find one, SetHidden and SetAllOptionalHidden change the choices, SetHiddenInRange and RangeState do the same for a whole span of positions, Apply writes them through a layout, Adopt reads them back from a saved set and ResetToAuthored puts the choices, the sheet and the printed header directions back where the dictionary started them. The class reads the dictionary alone: the worksheet is ShowHideLayout's work and the saved choices are ShowHideStore's.
A SECTION IS A SPAN OF POSITIONS
Hiding a whole section is SetHiddenInRange over the positions SectionMap recorded for it. Nothing about a section is stored here or anywhere else: the choice lands on the member entries, so it travels through the store and through a migration file with no column of its own, and there is no second record that could disagree with the first.
FOUR KINDS OF ENTRY
A variable the dictionary marks as hidden is EXCLUDED. It never enters the list, because the designer said the user must never see it.
Of the variables that do enter, each is one of three kinds:
mandatory listed, always visible, the user cannot change it. locked listed, always hidden, the user cannot change it. A calculated column on a printed sheet or on a CRF lands here, and so does an automatic list: both are named by their CONTROL, never by the "list auto" column, which is about something else entirely. free listed, starts where the dictionary says, follows the user.
IsFree is the single question a click handler asks before it changes anything.
WHICH DICTIONARY COLUMN SAYS WHAT
HList, VList visibility Printed register book CRF crf status
The position of a variable comes from column index, and from crf index on
the CRF layer. A variable with no position is listed, and the layout leaves it
where it is.
THE STATE IS A BOOLEAN
Hidden is True or False. The display words the form shows ("Shown", "Hidden", "Mandatory") are translated at the form and stored nowhere. A user who changes the interface language between two sessions keeps every choice.
Depends on: LLdictionary, LLVariables, ShowHideLayout, BetterArray, Checking, Dictionary column names, The one register book value that asks for a turned header
Version: 1.2 (2026-08-11)
Instantiation
Create #
create
Build the entry list of one layer of one sheet
Signature:
Public Function Create(ByVal dict As LLdictionary, _
ByVal layer As Byte, _
ByVal sheetName As String) As ShowHide
The factory and the build it runs.
Walks the dictionary once, keeps the variables of the named sheet whose sheet type suits the layer, and files each one as mandatory, locked or free. The dictionary is prepared when it arrives unprepared, because the four columns this class reads (visibility, crf status, column index, crf index) are all written by Prepare.
Parameters:
dict: LLdictionary. The dictionary to read.layer: Byte. A ShowHideWorksheetLayer value. Which of the four layers to build.sheetName: String. The base sheet name, with no print_ or crf_ prefix.
Returns: ShowHide. The entry list, ready to read.
Throws:
- ProjectError.ObjectNotInitialized When the dictionary is Nothing.
- ProjectError.InvalidArgument When the sheet name is empty or the layer is outside the four values.
Accessors
EntryCount #
entry-count
The number of entries the user is offered
Signature:
Public Property Get EntryCount() As Long
What the list holds, and what each entry is.
TargetLayer #
target-layer
The layer this list was built for
Signature:
Public Property Get TargetLayer() As Byte
SheetName #
sheet-name
The base sheet name the entries belong to
Signature:
Public Property Get SheetName() As String
FieldKey #
field-key
The variable name of one entry
Signature:
Public Function FieldKey(ByVal index As Long) As String
Parameters:
index: Long. A one based entry index.
Returns: String. The variable name as the dictionary spells it.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
HeaderText #
header-text
The label the form shows for one entry
Signature:
Public Function HeaderText(ByVal index As Long) As String
Parameters:
index: Long. A one based entry index.
Returns: String. The main label, carrying its sub section for a geo or hf variable.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
IsHidden #
is-hidden
Whether one entry is hidden right now
Signature:
Public Function IsHidden(ByVal index As Long) As Boolean
A mandatory entry answers False and a locked entry answers True, whatever the user asked for. Every other entry answers the stored choice.
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the variable is hidden.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
IsMandatory #
is-mandatory
Whether one entry is always visible
Signature:
Public Function IsMandatory(ByVal index As Long) As Boolean
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the user cannot hide the variable.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
IsLocked #
is-locked
Whether one entry is always hidden
Signature:
Public Function IsLocked(ByVal index As Long) As Boolean
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the variable is held hidden and the user cannot show it.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
IsFree #
is-free
Whether the user may change one entry
Signature:
Public Function IsFree(ByVal index As Long) As Boolean
The single guard a click handler asks. An entry that is neither mandatory nor locked follows whatever the user picks.
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the entry follows the user.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
PositionIndex #
position-index
Where one entry sits on the worksheet
Signature:
Public Function PositionIndex(ByVal index As Long) As Long
Parameters:
index: Long. A one based entry index.
Returns: Long. The column or row number, or 0 when the dictionary gives none.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
ControlType #
control-type
The dictionary control of one entry
Signature:
Public Function ControlType(ByVal index As Long) As String
Parameters:
index: Long. A one based entry index.
Returns: String. The control value in lower case, such as "geo1" or "formula".
Throws:
- ProjectError.InvalidArgument When the index is out of range.
AuthoredVertical #
authored-vertical
The header direction the dictionary asked for
Signature:
Public Function AuthoredVertical(ByVal index As Long) As Boolean
Read only, and true for a variable whose register book reads
"print, vertical header". A reset restores this direction without the entry
list ever owning the live orientation of the sheet.
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the printed header should be turned.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
Lookup
IndexOf #
index-of
Find an entry by variable name
Signature:
Public Function IndexOf(ByVal fieldKey As String) As Long
Finding an entry by its variable name.
The name is trimmed and lower cased on the way in and on the way out, so a dictionary name carrying a stray space is still reachable.
Parameters:
fieldKey: String. The variable name to look for.
Returns: Long. The one based entry index, or 0 when the name is absent.
HasField #
has-field
Whether a variable name is in the list
Signature:
Public Function HasField(ByVal fieldKey As String) As Boolean
Parameters:
fieldKey: String. The variable name to look for.
Returns: Boolean. True when the list carries the name.
Choices
SetHidden #
set-hidden
Hide or show one entry
Signature:
Public Sub SetHidden(ByVal index As Long, ByVal hidden As Boolean)
Changing what the user sees.
A mandatory or locked entry keeps its state and the call returns quietly, so a caller that loops the whole list needs no guard of its own.
Parameters:
index: Long. A one based entry index.hidden: Boolean. True to hide the variable.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
SetAllOptionalHidden #
set-all-optional-hidden
Hide or show every entry the user owns
Signature:
Public Sub SetAllOptionalHidden(ByVal hidden As Boolean)
Parameters:
hidden: Boolean. True to hide all the free entries.
SetHiddenInRange #
set-hidden-in-range
Hide or show every entry sitting in a span of positions
Signature:
Public Function SetHiddenInRange(ByVal firstPos As Long, _
ByVal lastPos As Long, _
ByVal hidden As Boolean) As Long
What hiding a whole section comes down to. The span is a range of column numbers on an HList sheet and of row numbers on a VList one, which is what SectionMap records for each section.
Hiding a section stores nothing of its own: the choice lands on each member entry, so the store, the show/hide form and a migration file all carry a collapsed section without knowing the word "section". Nothing can drift out of step with anything else, because there is only one record of the choice.
A mandatory or locked entry inside the span keeps its state, as it does everywhere else. So a section holding a mandatory variable never disappears whole, and the count says how many entries actually moved.
Parameters:
firstPos: Long. One end of the span.lastPos: Long. The other end of the span.hidden: Boolean. True to hide the span.
Returns: Long. How many entries the call changed.
RangeState #
range-state
Where a span of positions stands
Signature:
Public Function RangeState(ByVal firstPos As Long, ByVal lastPos As Long) As Byte
Read from the entries the user owns, so a section whose only visible column is a mandatory one still answers Hidden and a caller toggling it offers Show.
Parameters:
firstPos: Long. One end of the span.lastPos: Long. The other end of the span.
Returns: Byte. A ShowHideRangeState value. Empty when no entry sits in the span, Fixed when none of those that do is free, and otherwise Shown, Hidden or Mixed by what the free entries say.
Worksheet
Apply #
apply
Put the worksheet in the state the list describes
Signature:
Public Function Apply(ByVal layout As ShowHideLayout) As Long
The two calls that put the list and a sheet in step.
The one place the entry list reaches a sheet, and it goes through the layout, so the row versus column question and the protection bracket are answered in one place. Entries with no position are skipped.
Parameters:
layout: ShowHideLayout. The sheet to reconcile.
Returns: Long. The number of positions that were set.
Adopt #
adopt
Read the worksheet back into the list
Signature:
Public Function Adopt(ByVal layout As ShowHideLayout) As Long
For the case where the user hid a column by hand rather than through the form. Mandatory and locked entries keep what the dictionary said.
Parameters:
layout: ShowHideLayout. The sheet to read.
Returns: Long. The number of entries that were read.
ResetToAuthored #
reset-to-authored
Put the choices and the sheet back where the dictionary started them
Signature:
Public Function ResetToAuthored(ByVal layout As ShowHideLayout) As Long
The reset button of the advanced form comes through here, once per worksheet.
Every free entry goes back to the hidden or visible state the dictionary
authored, the sheet is put in step through Apply, and on a printed sheet each
header direction goes back to what register book asked. Mandatory and locked
entries never left their authored state, so they are covered by the same walk.
Parameters:
layout: ShowHideLayout. The sheet to reconcile, or Nothing to reset the choices alone.
Returns: Long. The number of positions Apply set.
Build
Initialise #
initialise
Fill the entry list from the dictionary
Signature:
Public Sub Initialise(ByVal dict As LLdictionary, _
ByVal layer As Byte, _
ByVal sheetName As String)
The dictionary walk the factory runs.
Public because the factory calls it on a fresh instance. Every variable of the sheet is read once and the arrays are trimmed to what matched.
Parameters:
dict: LLdictionary. The dictionary to read.layer: Byte. A ShowHideWorksheetLayer value. The layer being built.sheetName: String. The base sheet name.
Internal members (not exported)
Helpers
EffectiveHidden #
effective-hidden
Work out the state one entry really has
Signature:
Private Function EffectiveHidden(ByVal index As Long) As Boolean
Private workers of the build and the accessors.
Parameters:
index: Long. A one based entry index.
Returns: Boolean. True when the entry is hidden.
PositionInRange #
position-in-range
Whether one entry sits inside a span of positions
Signature:
Private Function PositionInRange(ByVal position As Long, _
ByVal firstPos As Long, _
ByVal lastPos As Long) As Boolean
The two bounds are read in either order, so a caller that hands them over the
other way round gets the same answer. An entry with no position, which is what
a variable the dictionary gives no column index looks like, is in no span.
Parameters:
position: Long. The entry position.firstPos: Long. One end of the span.lastPos: Long. The other end of the span.
Returns: Boolean. True when the position falls inside the span.
MatchesSheet #
matches-sheet
Whether a variable belongs to the sheet being built
Signature:
Private Function MatchesSheet(ByVal vars As LLVariables, ByVal varName As String) As Boolean
Parameters:
vars: LLVariables. The variable reader.varName: String. The variable to test.
Returns: Boolean. True when the sheet names agree.
MatchesLayer #
matches-layer
Whether a dictionary sheet type suits the layer being built
Signature:
Private Function MatchesLayer(ByVal sheetType As String) As Boolean
The dictionary vocabulary is "vlist1D" and "hlist2D". A printed sheet and a CRF are both derived from an hlist2D sheet, so all three of HList, Printed and CRF test for "hlist". The CRF case used to test for "crf", a word the vocabulary has never held, so every CRF list came back empty.
Parameters:
sheetType: String. The dictionarysheet typevalue, lower cased.
Returns: Boolean. True when the variable belongs on this layer.
StatusForLayer #
status-for-layer
Read the status column that belongs to the layer
Signature:
Private Function StatusForLayer(ByVal vars As LLVariables, _
ByVal varName As String, _
ByVal registerBook As String, _
ByVal hasVisibility As Boolean, _
ByVal hasStatus As Boolean, _
ByVal hasCrfStatus As Boolean) As String
Parameters:
vars: LLVariables. The variable reader.varName: String. The variable to read.registerBook: String. Theregister bookvalue, already read.hasVisibility: Boolean. Whether the dictionary carriesvisibility.hasStatus: Boolean. Whether the dictionary carriesstatus.hasCrfStatus: Boolean. Whether the dictionary carriescrf status.
Returns: String. The status text for this layer.
IsMandatoryStatus #
is-mandatory-status
Whether a status makes an entry always visible
Signature:
Private Function IsMandatoryStatus(ByVal layerStatus As String, _
ByVal controlVal As String, _
ByVal layer As Byte) As Boolean
The first geo level of an HList sheet is mandatory whatever its status says, because the geo cascade of every other level reads it.
Parameters:
layerStatus: String. The status of this layer, lower cased.controlVal: String. The control value, lower cased.layer: Byte. A ShowHideWorksheetLayer value. The layer being built.
Returns: Boolean. True when the user cannot hide the entry.
IsLockedStatus #
is-locked-status
Whether a status holds an entry hidden
Signature:
Private Function IsLockedStatus(ByVal layerStatus As String, _
ByVal controlVal As String, _
ByVal layer As Byte, _
ByVal isMandatoryEntry As Boolean) As Boolean
A calculated column and an automatic list have nothing to give on a printed sheet or a CRF, so both layers hold them hidden. A mandatory entry is never locked as well.
Parameters:
layerStatus: String. The status of this layer, lower cased.controlVal: String. The control value, lower cased.layer: Byte. A ShowHideWorksheetLayer value. The layer being built.isMandatoryEntry: Boolean. Whether the entry is already mandatory.
Returns: Boolean. True when the entry is held hidden.
InitialHidden #
initial-hidden
The state a free entry starts in
Signature:
Private Function InitialHidden(ByVal layerStatus As String) As Boolean
The register book vocabulary of a printed sheet is "print, horizontal
header", "print, vertical header" and "hidden". An empty cell means the column
prints, which is why the default answer is visible.
Parameters:
layerStatus: String. The status of this layer, lower cased.
Returns: Boolean. True when the entry starts hidden.
SafeValue #
safe-value
Read a dictionary cell and answer empty when it is absent
Signature:
Private Function SafeValue(ByVal vars As LLVariables, _
ByVal colName As String, _
ByVal varName As String) As String
Parameters:
vars: LLVariables. The variable reader.colName: String. The column to read.varName: String. The variable to read.
Returns: String. The cell value, or an empty string.
Normalise #
normalise
Trim and lower case a value for comparison
Signature:
Private Function Normalise(ByVal value As String) As String
Parameters:
value: String. The text to normalise.
Returns: String. The trimmed, lower cased text.
NormaliseKey #
normalise-key
Build the lookup key of a variable name
Signature:
Private Function NormaliseKey(ByVal value As String) As String
The same shape on the way in and on the way out. A dictionary name carrying a trailing space used to be stored untrimmed and looked up trimmed, so its saved state was dropped on every load.
Parameters:
value: String. The variable name.
Returns: String. The lookup key.
EnsureValidIndex #
ensure-valid-index
Refuse an entry index outside the list
Signature:
Private Sub EnsureValidIndex(ByVal index As Long)
Parameters:
index: Long. The index to check.
Throws:
- ProjectError.InvalidArgument When the index is out of range.
ValidateLayer #
validate-layer
Refuse a layer outside the four values
Signature:
Private Sub ValidateLayer(ByVal layer As Byte)
Parameters:
layer: Byte. A ShowHideWorksheetLayer value. The layer to check.
Throws:
- ProjectError.InvalidArgument When the layer is unknown.
ThrowError #
throw-error
Raise a project error naming this class
Signature:
Private Sub ThrowError(ByVal errNumber As ProjectError, ByVal message As String)
Parameters:
errNumber: ProjectError. The error to raise.message: String. What went wrong.
Used in (14 file(s))
- LLExporter.cls
- LLImporter.cls
- LLdictionary.cls
- LLGeo.cls
- Linelist.cls
- SectionMap.cls
- VarWriter.cls
- SectionShowHide.cls
- ShowHideLayout.cls
- ShowHideStore.cls
- EventsLinelistButtons.bas
- FormLogicAdvanced.bas
- TestSectionShowHide.bas
- TestShowHide.bas