SectionBuilder
Builds all sections, subsections, and variables for a single linelist worksheet. Given a sheet name and dictionary start row, the builder scans the dictionary for matching rows, groups them by section and subsection, delegates variable writing to VarWriter, and applies merged-cell section and subsection header formatting. Supports both HList (horizontal) and VList (vertical) layouts via the layer byte.
Depends on: ILinelistSpecs, ILLdictionary, ILLVariables, ILLFormat, IDropdownLists, VarWriter, LLVariables, Row/column constants for section and subsection headers
Version: 1.0 (2026-02-10)
Instantiation
create #
Create a new SectionBuilder instance
Signature:
Public Function Create(ByVal layer As Byte, _
ByVal specs As ILinelistSpecs, _
ByVal wksh As Worksheet, _
Optional ByVal printWksh As Worksheet = Nothing, _
Optional ByVal crfWksh As Worksheet = Nothing, _
Optional ByVal dropdownObj As IDropdownLists = Nothing, _
Optional ByVal customDropdownObj As IDropdownLists = Nothing) As ISectionBuilder
Factory method on the predeclared instance. Validates that specs and wksh are not Nothing, then initialises a new SectionBuilder with the given layer, specifications, and optional companion worksheets and dropdown managers. Returns the instance through the ISectionBuilder interface.
Parameters:
layer: Byte. SectionBuilderMode enum value (HList=1, VList=2).specs: ILinelistSpecs. The linelist specifications object.wksh: Worksheet. The target main worksheet.printWksh: Optional Worksheet. Printed companion worksheet (HList only).crfWksh: Optional Worksheet. CRF companion worksheet (HList only).dropdownObj: Optional IDropdownLists. Dropdown lists manager.customDropdownObj: Optional IDropdownLists. Custom dropdown lists manager.
Returns: ISectionBuilder. A fully initialised instance ready for use.
Throws:
- VbObjectError+516 When specs or wksh is Nothing.
Entry Point
build #
Build all sections, subsections, and variables for a sheet
Signature:
Public Sub Build(ByVal sheetName As String, ByVal startRow As Long)
Scans the dictionary for rows matching sheetName starting from startRow. Groups consecutive rows by their "main section" column value, then delegates to BuildSubSections for subsection grouping and variable writing. After all variables in a section are written, applies merged-cell section header formatting via FormatSection. Stops when the sheet name changes or the dictionary ends.
Parameters:
sheetName: String. The sheet name as it appears in the dictionary "sheet name" column.startRow: Long. The first data row index in the dictionary for this sheet (1-based).
Internal members (not exported)
Instantiation
self #
Current object instance
Signature:
Public Property Get Self() As ISectionBuilder
Returns the current instance cast to the ISectionBuilder interface, used by the Create factory to return the newly built object.
Returns: ISectionBuilder. The current instance.
Internal Setters
internal-layer #
Assign the layer mode
Signature:
Public Property Let InternalLayer(ByVal layer As Byte)
Properties used by the factory only during instantiation.
Parameters:
layer: Byte. SectionBuilderMode enum value.
internal-specs #
Assign the linelist specifications
Signature:
Public Property Set InternalSpecs(ByVal specs As ILinelistSpecs)
Parameters:
specs: ILinelistSpecs. The specifications object.
internal-wksh #
Assign the target main worksheet
Signature:
Public Property Set InternalWksh(ByVal wksh As Worksheet)
Parameters:
wksh: Worksheet. The main worksheet to build on.
internal-print-wksh #
Assign the printed companion worksheet
Signature:
Public Property Set InternalPrintWksh(ByVal wksh As Worksheet)
Parameters:
wksh: Worksheet. The printed companion worksheet.
internal-crf-wksh #
Assign the CRF companion worksheet
Signature:
Public Property Set InternalCRFWksh(ByVal wksh As Worksheet)
Parameters:
wksh: Worksheet. The CRF companion worksheet.
internal-dropdown #
Assign the dropdown lists manager
Signature:
Public Property Set InternalDropdown(ByVal dropdownObj As IDropdownLists)
Parameters:
dropdownObj: IDropdownLists. The dropdown manager.
internal-custom-dropdown #
Assign the custom dropdown lists manager
Signature:
Public Property Set InternalCustomDropdown(ByVal dropdownObj As IDropdownLists)
Parameters:
dropdownObj: IDropdownLists. The custom dropdown manager.
Cached Accessors
dictionary #
Lazy-loaded dictionary accessor
Signature:
Private Property Get Dictionary() As ILLdictionary
Lazy-loaded accessors for frequently used dependency objects. Returns the cached ILLdictionary instance. On first access, retrieves it from the specifications object and caches it for subsequent calls.
Returns: ILLdictionary. The linelist dictionary.
variables #
Lazy-loaded variables accessor
Signature:
Private Property Get Variables() As ILLVariables
Returns the cached ILLVariables instance. On first access, creates it from the dictionary via LLVariables.Create and caches it.
Returns: ILLVariables. The variables helper for dictionary lookups.
design-format #
Design format accessor
Signature:
Private Property Get DesignFormat() As ILLFormat
Returns: ILLFormat. The formatting object from the specifications.
Section Boundary Detection
find-section-end #
Find the last row of a section
Signature:
Private Function FindSectionEnd(ByVal startRow As Long, _
ByVal sectionName As String, _
ByVal sheetName As String, _
ByVal sectionRng As Range, _
ByVal sheetRng As Range, _
ByVal dataEndRow As Long) As Long
Starting from startRow, scans forward until the section name or sheet name changes, then returns the row just before the change. When the end of the data range is reached without a change, returns the last data row.
Parameters:
startRow: Long. The row to start scanning from.sectionName: String. The current section name to match.sheetName: String. The current sheet name to match.sectionRng: Range. The "main section" data column range.sheetRng: Range. The "sheet name" data column range.dataEndRow: Long. The last row of data in the dictionary.
Returns: Long. The 1-based row index of the last row in the section.
Subsection Processing
build-sub-sections #
Build all subsections within a section range
Signature:
Private Sub BuildSubSections(ByVal sectionStart As Long, _
ByVal sectionEnd As Long, _
ByVal sheetName As String)
Iterates through dictionary rows from sectionStart to sectionEnd, grouping consecutive rows by the "sub section" column value. For each subsection group, delegates variable writing to BuildVariables and then applies subsection header formatting via FormatSubSection.
Parameters:
sectionStart: Long. The first row of the section.sectionEnd: Long. The last row of the section.sheetName: String. The current sheet name.
find-sub-section-end #
Find the last row of a subsection
Signature:
Private Function FindSubSectionEnd(ByVal startRow As Long, _
ByVal subSectionName As String, _
ByVal sectionName As String, _
ByVal sheetName As String, _
ByVal subSectionRng As Range, _
ByVal sectionRng As Range, _
ByVal sheetRng As Range, _
ByVal maxRow As Long) As Long
Starting from startRow, scans forward until the subsection name, section name, or sheet name changes, then returns the row just before the change. Constrained by maxRow (the section boundary).
Parameters:
startRow: Long. The row to start scanning from.subSectionName: String. The current subsection name to match.sectionName: String. The current section name to match.sheetName: String. The current sheet name to match.subSectionRng: Range. The "sub section" data column range.sectionRng: Range. The "main section" data column range.sheetRng: Range. The "sheet name" data column range.maxRow: Long. The last row of the enclosing section.
Returns: Long. The 1-based row index of the last row in the subsection.
Variable Building
build-variables #
Build all variables within a subsection range
Signature:
Private Sub BuildVariables(ByVal subSecStart As Long, ByVal subSecEnd As Long)
Creates a single VarWriter instance configured with the current layer, specifications, worksheets, and dropdown managers, then iterates from subSecStart to subSecEnd, calling WriteVariable for each variable name found in the dictionary. Reusing one VarWriter across the subsection avoids repeated factory overhead.
Parameters:
subSecStart: Long. The first dictionary row of the subsection.subSecEnd: Long. The last dictionary row of the subsection.
Depends on:
- VarWriter
Section Formatting
format-section #
Format a section header
Signature:
Private Sub FormatSection(ByVal sectionName As String, _
ByVal startRow As Long, _
ByVal endRow As Long, _
ByVal sheetName As String)
Dispatches to FormatHListSection or FormatVListSection based on the current layer. Resolves the first and last variable names for the section range to calculate column or row indices for the merged header.
Parameters:
sectionName: String. The section title to display.startRow: Long. The first dictionary row of the section.endRow: Long. The last dictionary row of the section.sheetName: String. The current sheet name.
format-hlist-section #
Format an HList section header
Signature:
Private Sub FormatHListSection(ByVal sectionName As String, _
ByVal firstVarName As String, _
ByVal lastVarName As String, _
ByVal sheetName As String)
Merges cells horizontally across the column range at HLIST_SEC_ROW on the main sheet, writes the section name, and applies HListSection formatting. Repeats for the printed companion when available. Also writes a CRF section header when a CRF worksheet is present, using the first variable's "crf index" to calculate the CRF row offset.
Parameters:
sectionName: String. The section title to display.firstVarName: String. The first variable name in the section.lastVarName: String. The last variable name in the section.sheetName: String. The current sheet name.
format-vlist-section #
Format a VList section header
Signature:
Private Sub FormatVListSection(ByVal sectionName As String, _
ByVal firstVarName As String, _
ByVal lastVarName As String, _
ByVal sheetName As String)
Merges cells vertically across the row range at VLIST_SEC_COL on the main sheet, writes the section name, and applies VListSection formatting. No companion sheets are involved for VList layers.
Parameters:
sectionName: String. The section title to display.firstVarName: String. The first variable name in the section.lastVarName: String. The last variable name in the section.sheetName: String. The current sheet name.
Subsection Formatting
format-sub-section #
Format a subsection header
Signature:
Private Sub FormatSubSection(ByVal subSectionName As String, _
ByVal startRow As Long, _
ByVal endRow As Long, _
ByVal sheetName As String)
Dispatches to FormatHListSubSection or FormatVListSubSection based on the current layer.
Parameters:
subSectionName: String. The subsection title to display.startRow: Long. The first dictionary row of the subsection.endRow: Long. The last dictionary row of the subsection.sheetName: String. The current sheet name.
format-hlist-sub-section #
Format an HList subsection header
Signature:
Private Sub FormatHListSubSection(ByVal subSectionName As String, _
ByVal startRow As Long, _
ByVal endRow As Long, _
ByVal sheetName As String)
Merges cells horizontally across the column range at HLIST_SUBSEC_ROW on the main sheet, writes the subsection name, and applies HListSubSection formatting. Repeats for the printed companion when available. Also writes a CRF subsection header when a CRF worksheet is present.
Parameters:
subSectionName: String. The subsection title to display.startRow: Long. The first dictionary row of the subsection.endRow: Long. The last dictionary row of the subsection.sheetName: String. The current sheet name.
format-vlist-sub-section #
Format a VList subsection header
Signature:
Private Sub FormatVListSubSection(ByVal subSectionName As String, _
ByVal startRow As Long, _
ByVal endRow As Long, _
ByVal sheetName As String)
Merges cells vertically across the row range at VLIST_SUBSEC_COL on the main sheet, writes the subsection name, and applies VListSubSection formatting.
Parameters:
subSectionName: String. The subsection title to display.startRow: Long. The first dictionary row of the subsection.endRow: Long. The last dictionary row of the subsection.sheetName: String. The current sheet name.
Error Handling
throw-error #
Raise an error with the class name as source
Signature:
Private Sub ThrowError(ByVal errNumber As Long, ByVal errorMessage As String)
Parameters:
errorMessage: String. Human-readable description of the failure.
Throws:
- VbObjectError+516 Always raises the specified error.
Interface Implementation
ISectionBuilder_Build #
Signature:
Private Sub ISectionBuilder_Build(ByVal sheetName As String, ByVal startRow As Long)
Delegated members satisfying the ISectionBuilder contract.