LinelistSpecs

Modern facade that wraps a specifications workbook and exposes lazy-loaded, cached accessors for every collaborator object (dictionary, choices, translations, geo, analysis, passwords, format, exports, formulas). Provides lifecycle orchestration methods for importing data from external setup workbooks, preparing the dictionary with preserved sheet names, exporting specifications to a destination linelist workbook, and surfacing user-facing error dialogs. Uses a PredeclaredId factory pattern so callers construct instances via LinelistSpecs.Create(workbook) and receive an ILinelistSpecs interface reference.

Depends on: ILLdictionary, ILLChoices, ILLTranslation, IDesignerTranslation, ILLGeo, ILLExport, IAnalysis, IPasswords, ILLFormat, ILinelistBuildService, ITemporaryRepos, TemporaryRepos, IFormulaData, ILLVariables, IFormulas, ITranslationObject, IApplicationState, ApplicationState, BetterArray, LLdictionary, LLChoices, LLTranslation, DesignerTranslation, LLGeo, LLExport, Analysis, Passwords, LLFormat, FormulaData, LLVariables, Formulas

Version: 1.1 (2026-02-16)

Factory helpers

Create #

create

Create a new specification facade from a workbook

Signature:

Public Function Create(ByVal specsWorkbook As Workbook) As ILinelistSpecs

Construction and identity accessors. Validates the workbook structure upfront (checking for all required worksheets and named ranges), then constructs a new LinelistSpecs instance with caches initialised. Returns the ILinelistSpecs interface.

Parameters:

  • specsWorkbook: Workbook. The specifications workbook to wrap.

Returns: ILinelistSpecs. A fully initialised facade ready for use.

Throws:

  • ProjectError.ObjectNotInitialized When specsWorkbook is Nothing.
  • ProjectError.ElementNotFound When required worksheets are missing.

DesWorkbook #

des-workbook

Designer workbook backing all specification queries

Signature:

Public Property Get DesWorkbook() As Workbook

Returns the designer/specifications workbook reference. Raises an error if the workbook has not been assigned via the factory method.

Returns: Workbook. The designer workbook.

Throws:

  • ProjectError.ObjectNotInitialized When the workbook is not set.

State management

ResetCaches #

reset-caches

Reset every cached collaborator

Signature:

Public Sub ResetCaches()

Cache invalidation for collaborator objects, translations, and categories. Clears all cached collaborator objects, the translation scope cache, and the category cache. Call after importing new data so subsequent reads query the workbook again.


Category helpers

Categories #

categories

Resolve category values for a variable with caching

Signature:

Public Function Categories(ByVal varName As String, Optional ByVal useShortlabels As Boolean = False) As BetterArray

Category resolution and caching for choice-type variables. Returns the list of category values for a choice-type variable (choice_manual, choice_multiple, choice_custom, or choice_formula). Results are cached using parallel key/value BetterArrays for efficient repeated access. Always returns a cloned BetterArray to prevent callers from modifying the cached copy.

Parameters:

  • varName: String. The variable name whose categories to resolve.
  • useShortlabels: Boolean. When True, returns short labels. Defaults to False.

Returns: BetterArray. Cloned list of category values.

Throws:

  • ProjectError.InvalidArgument When varName is empty.
  • ProjectError.ElementNotFound When the variable has no selectable categories.

Core accessors

Dictionary #

dictionary

Linelist dictionary

Signature:

Public Property Get Dictionary() As ILLdictionary

Public property accessors for each collaborator object, exposing the lazy-loaded instances through their respective interfaces. Returns the ILLdictionary instance providing column and row access to the Dictionary worksheet. Lazy-loaded on first access.

Returns: ILLdictionary. The dictionary collaborator.


Choices #

choices

Choices catalogue

Signature:

Public Property Get Choices() As ILLChoices

Returns the ILLChoices instance providing category lookups from the Choices worksheet. Lazy-loaded on first access.

Returns: ILLChoices. The choices collaborator.


DesignFormat #

design-format

Visual formatting specifications

Signature:

Public Property Get DesignFormat() As ILLFormat

Returns the ILLFormat instance providing sheet and cell formatting methods based on the __formatter worksheet. Lazy-loaded on first access.

Returns: ILLFormat. The format collaborator.


AnalysisObject #

analysis

Analysis setup specifications

Signature:

Public Property Get AnalysisObject() As IAnalysis

Returns the IAnalysis instance providing access to the Analysis worksheet configuration. Lazy-loaded on first access.

Returns: IAnalysis. The analysis collaborator.


ExportObject #

export-object

Export column specifications

Signature:

Public Property Get ExportObject() As ILLExport

Returns the ILLExport instance providing access to export column definitions from the Exports worksheet. Lazy-loaded on first access.

Returns: ILLExport. The export collaborator.


Password #

password

Password manager

Signature:

Public Property Get Password() As IPasswords

Returns the IPasswords instance providing workbook and sheet protection utilities from the __pass worksheet. Lazy-loaded on first access.

Returns: IPasswords. The password collaborator.


GeoObject #

geo-object

Geographic data manager

Signature:

Public Property Get GeoObject() As ILLGeo

Returns the ILLGeo instance providing geographic hierarchy lookups from the Geo worksheet. Lazy-loaded on first access.

Returns: ILLGeo. The geo collaborator.


FormulaDataObject #

formula-data-object

Formula data provider

Signature:

Public Property Get FormulaDataObject() As IFormulaData

Returns the IFormulaData instance providing formula parsing support from the __formula worksheet. Lazy-loaded on first access.

Returns: IFormulaData. The formula data collaborator.


HasTemplate #

has-template

Whether the workbook uses a ribbon template

Signature:

Public Property Get HasTemplate() As Boolean

Reads the RNG_MainTemp named range on the Main worksheet and returns True when the value equals "has template".

Returns: Boolean. True when a template is configured.


Translations #

translations

Translation tables manager

Signature:

Public Property Get Translations() As ILLTranslation

Returns the ILLTranslation instance providing access to the linelist translation worksheet. Lazy-loaded on first access.

Returns: ILLTranslation. The translations collaborator.


DesignerTranslations #

designer-translations

Designer translation accessor

Signature:

Public Property Get DesignerTranslations() As IDesignerTranslation

Returns the IDesignerTranslation instance providing designer UI translations from the DesignerTranslation worksheet. Lazy-loaded on first access.

Returns: IDesignerTranslation. The designer translation collaborator.


TransObject #

trans-object

Scoped translation object

Signature:

Public Property Get TransObject(Optional ByVal translationScope As Byte = TranslationOfMessages) As ITranslationObject

Returns an ITranslationObject for the requested translation scope. Results are cached per scope using direct fields for each TranslationScope value (0-4), avoiding generic container overhead.

Parameters:

  • translationScope: Byte. The translation scope constant (e.g., TranslationOfMessages, TranslationOfDictionary). Defaults to TranslationOfMessages.

Returns: ITranslationObject. The scoped translation object.

Throws:

  • ProjectError.ElementNotFound When the scope is not available.

TemporarySheetName #

temporary-sheet-name

Temporary sheet name for a given scope

Signature:

Public Property Get TemporarySheetName(ByVal scope As Byte) As String

Returns the fixed worksheet name used for temporary internal sheets, mapped from the TempSheetScope enum (TempSheetAnalysis, TempSheetList, etc.) to its canonical name string.

Parameters:

  • scope: Byte. A TempSheetScope enum value.

Returns: String. The worksheet name string.

Throws:

  • ProjectError.InvalidArgument When the scope is not recognised.

Value #

value

Configuration value by tag name

Signature:

Public Property Get Value(ByVal tagName As String) As String

Returns a configuration value from the Main worksheet for the given tag name. The special tag "numberofexports" returns the export count from the Exports worksheet; all other tags resolve the named range directly on the Main worksheet.

Parameters:

  • tagName: String. The configuration key to look up.

Returns: String. The configuration value, or empty string if tagName is empty.


Workbook orchestration

Prepare #

prepare

Prepare all specifications using a build service

Signature:

Public Sub Prepare(ByVal buildService As ILinelistBuildService, ByVal setupPath As String)

Lifecycle methods for importing, preparing, exporting, and error-managing the specifications workbook. Orchestrates the full specification preparation workflow:

  1. Creates a temporary repository for working files.
  2. Creates a new output workbook (from template if configured).
  3. Exports pass-through components directly from setup to linelist.
  4. Exports designer-sourced components (geo, passwords, translations, formatter, language HiddenNames) to the linelist.
  5. Builds domain manager instances on the linelist workbook.
  6. Retrieves exported domain instances from the service.
  7. Prepares the dictionary with preserved sheet names and geo references.
  8. Adds the "list auto" column if not already present.
  9. Translates and sorts all collaborators using dictionary translations. Handles errors with cleanup and busy-state restoration.

Parameters:

  • buildService: ILinelistBuildService. The configured build service.
  • setupPath: String. Full path to the setup workbook.

Throws:

  • ProjectError.ObjectNotInitialized When buildService is Nothing.
  • ProjectError.ErrorUnexpectedState When an unexpected error occurs.

LLWorkbook #

ll-workbook

The output linelist workbook created during Prepare

Signature:

Public Property Get LLWorkbook() As Workbook

Returns the linelist workbook created by Prepare that received exported data from the import service. Returns Nothing before Prepare is called.

Returns: Workbook. The linelist workbook, or Nothing.


OutputTemporaryRepos #

temporary-repos

The temporary repository created during Prepare

Signature:

Public Property Get OutputTemporaryRepos() As ITemporaryRepos

Returns the ITemporaryRepos instance created by Prepare for working files. Returns Nothing before Prepare is called.

Returns: ITemporaryRepos. The temporary repository, or Nothing.


ErrorManage #

error-manage

Display an error dialog for specification failures

Signature:

Public Sub ErrorManage(Optional ByVal textMessage As String = vbNullString)

Shows a message box describing the error and informing the user that the linelist creation process is being aborted.

Parameters:

  • textMessage: String. Error description. Defaults to vbNullString.

Internal members (not exported)

Factory helpers

Self #

self

Interface-cast self reference

Signature:

Public Property Get Self() As ILinelistSpecs

Returns the current instance cast as ILinelistSpecs for fluent construction patterns within the factory method.

Returns: ILinelistSpecs. This instance as its interface type.


InternalWorkbook #

internal-workbook

Setter for the backing workbook reference

Signature:

Public Property Set InternalWorkbook(ByVal specsWorkbook As Workbook)

Used during construction to assign the workbook before caches are initialised. Not part of the public interface.


State management

ResetObjectCaches #

reset-object-caches

Clear all collaborator object references

Signature:

Private Sub ResetObjectCaches()

ResetTranslationCache #

reset-translation-cache

Clear the translation scope cache

Signature:

Private Sub ResetTranslationCache()

ResetCategoryCache #

reset-category-cache

Clear the category list cache

Signature:

Private Sub ResetCategoryCache()

Guard helpers

EnsureWorkbook #

ensure-workbook

Verify that the backing workbook is assigned

Signature:

Private Sub EnsureWorkbook()

Lazy-initialisation guards for the workbook and category arrays.

Throws:


EnsureCategoryArrays #

ensure-category-arrays

Create the parallel category arrays if they do not exist

Signature:

Private Sub EnsureCategoryArrays()

Worksheet resolution

ResolveSheet #

resolve-sheet

Resolve a worksheet by name with optional error surfacing

Signature:

Private Function ResolveSheet(ByVal sheetName As String, _
                              Optional ByVal allowMissing As Boolean = False) As Worksheet

Direct worksheet lookups by name within the specifications workbook. Looks up a worksheet in the specifications workbook by name. When the sheet is not found and allowMissing is False, raises a descriptive error.

Parameters:

Returns: Worksheet. The resolved worksheet, or Nothing if allowMissing.

Throws:


External workbook helpers

EnterBusyState #

enter-busy-state

Transition the application into a busy state

Signature:

Private Sub EnterBusyState(ByRef busyScope As IApplicationState)

Utilities for opening, closing, and validating external workbooks during the Prepare workflow. Creates or refreshes an ApplicationState snapshot and applies the busy state (suppressing screen updates and calculation) if not already busy.

Parameters:


ImportGeobase #

import-geobase

Import geobase data from the user-specified path

Signature:

Private Sub ImportGeobase(ByVal geoObj As ILLGeo)

Reads the geobase file path from the Main worksheet. If the path is not empty, opens the geobase workbook, sets the dictionary language on the exported geo worksheet via RNG_MetaLang, calls geoObj.Import to populate the output geo sheet, then closes the geobase workbook. Silently skips if the path is empty or the file cannot be opened.

Parameters:


ExitBusyState #

exit-busy-state

Restore the application from a busy state

Signature:

Private Sub ExitBusyState(ByRef busyScope As IApplicationState)

Parameters:


BuildPreservedSheetNames #

build-preserved-sheet-names

Build the list of sheet names to preserve during dictionary preparation

Signature:

Private Function BuildPreservedSheetNames(ByVal messageTranslations As ITranslationObject) As BetterArray

Collects all specification sheet names and temporary sheet names into a BetterArray, then appends translated linelist sheet names (Admin, Analysis, Spatial, etc.) when message translations are available.

Parameters:

Returns: BetterArray. The list of preserved sheet names.


SafeTranslatedValue #

safe-translated-value

Look up a translation key, falling back to the key itself on failure

Signature:

Private Function SafeTranslatedValue(ByVal translations As ITranslationObject, ByVal key As String) As String

Parameters:

Returns: String. The translated value, or the key if translation fails.


ResetPostImportCaches #

reset-post-import-caches

Clear caches that become stale after importing new data

Signature:

Private Sub ResetPostImportCaches()

Resets the variables object, category cache, and translation cache so they are rebuilt from the freshly imported data.


Workbook validation

ValidateWorkbookReference #

validate-workbook-reference

Validate a workbook reference and its structure

Signature:

Private Sub ValidateWorkbookReference(ByVal specsWorkbook As Workbook)

Structural validation of specifications workbooks.

Throws:


ValidateWorkbookStructure #

validate-workbook-structure

Check that a workbook contains all required worksheets and named ranges

Signature:

Private Sub ValidateWorkbookStructure(ByVal specsWorkbook As Workbook)

Iterates the list of required sheet names and collects any that are missing. If the format sheet exists, also validates that the DESIGNTYPE named range is present.

Parameters:

Throws:


RequiredSheetNames #

required-sheet-names

Return the array of required designer worksheet names

Signature:

Private Function RequiredSheetNames() As Variant

Only includes sheets that LinelistSpecs reads directly from the designer workbook. Pass-through sheets (Dictionary, Choices, Analysis, Export) are excluded because the build service imports them from the setup file directly into the linelist.

Returns: Variant. Array of sheet name strings.


WorksheetExistsInternal #

worksheet-exists-internal

Test whether a worksheet exists in a workbook

Signature:

Private Function WorksheetExistsInternal(ByVal specsWorkbook As Workbook, _
                                         ByVal sheetName As String) As Boolean

Parameters:

Returns: Boolean. True when the worksheet exists.


RangeExistsInternal #

range-exists-internal

Test whether a named range exists on a worksheet

Signature:

Private Function RangeExistsInternal(ByVal hostSheet As Worksheet, _
                                     ByVal rangeName As String) As Boolean

Parameters:

Returns: Boolean. True when the named range exists.


JoinNames #

join-names

Join a BetterArray of names into a comma-separated, quoted string

Signature:

Private Function JoinNames(ByVal values As BetterArray) As String

Parameters:

Returns: String. Formatted string like "'Sheet1', 'Sheet2'".


SafeWorkbookName #

safe-workbook-name

Safely retrieve a workbook's name, returning "" on error

Signature:

Private Function SafeWorkbookName(ByVal specsWorkbook As Workbook) As String

Parameters:

Returns: String. The workbook name or "".


Collaborator ensures

EnsureExports #

ensure-exports

Lazy-load the export collaborator

Signature:

Private Sub EnsureExports()

Lazy-initialisation guards for each collaborator object. Each EnsureXxx method creates the collaborator from its backing worksheet on first access, then caches it for subsequent calls.


EnsureDictionary #

ensure-dictionary

Lazy-load the dictionary collaborator

Signature:

Private Sub EnsureDictionary()

Requires the export collaborator to be available first (for the number of exports parameter), then creates the dictionary from the Dictionary worksheet.


EnsureChoices #

ensure-choices

Lazy-load the choices collaborator

Signature:

Private Sub EnsureChoices()

EnsureTranslations #

ensure-translations

Lazy-load the translations collaborator

Signature:

Private Sub EnsureTranslations()

Creates the LLTranslation instance from the linelist translation worksheet.


EnsureDesignerTranslations #

ensure-designer-translations

Lazy-load the designer translations collaborator

Signature:

Private Sub EnsureDesignerTranslations()

EnsureGeo #

ensure-geo

Lazy-load the geo collaborator

Signature:

Private Sub EnsureGeo()

EnsureAnalysis #

ensure-analysis

Lazy-load the analysis collaborator

Signature:

Private Sub EnsureAnalysis()

EnsurePasswords #

ensure-passwords

Lazy-load the passwords collaborator

Signature:

Private Sub EnsurePasswords()

EnsureFormulaData #

ensure-formula-data

Lazy-load the formula data collaborator

Signature:

Private Sub EnsureFormulaData()

EnsureVariables #

ensure-variables

Lazy-load the variables collaborator

Signature:

Private Sub EnsureVariables()

Requires the dictionary to be available first, then creates the LLVariables instance from it.


EnsureFormat #

ensure-format

Lazy-load the format collaborator

Signature:

Private Sub EnsureFormat()

Resolves the design name from the DESIGNTYPE named range on the format sheet, then creates the LLFormat instance.


ResolveDesignName #

resolve-design-name

Extract the design name from the format worksheet's DESIGNTYPE range

Signature:

Private Function ResolveDesignName(ByVal formatSheet As Worksheet) As String

Parameters:

Returns: String. The trimmed design type name.

Throws:


EnsureCategoryLookup #

ensure-category-lookup

Ensure choices, variables, and category arrays are ready

Signature:

Private Sub EnsureCategoryLookup()

NumberOfExports #

number-of-exports

Return the number of exports defined in the export specifications

Signature:

Private Function NumberOfExports() As Long

Returns: Long. The export count.


List auto helpers

AddListAuto #

add-list-auto

Populate the "list auto" dictionary column for list_auto variables

Signature:

Private Sub AddListAuto()

Automatic list column generation for formula-based variables. Adds a "list auto" column to the dictionary, then finds all variables with control type "list_auto" and marks their control details with "list_auto_origin". For formula-type variables (formula, case_when, choice_formula), recursively traces referenced variables and marks them as well.


RecursiveListAuto #

recursive-list-auto

Recursively mark referenced variables in formula chains as list_auto

Signature:

Private Sub RecursiveListAuto(ByVal varName As String)

Parses the control details of a formula-type variable using the Formulas engine, extracts the list of referenced variables, marks each with "list_auto_origin", and recurses into any that are themselves formulas or case_when types.

Parameters:


Category helpers

FindCategoryIndex #

find-category-index

Search the category keys array for a matching key

Signature:

Private Function FindCategoryIndex(ByVal cacheKey As String) As Long

Parameters:

Returns: Long. The 1-based index if found, or 0 if not found.


ResolveCategoryList #

resolve-category-list

Build a category list from the choices sheet for a given variable

Signature:

Private Function ResolveCategoryList(ByVal varName As String, _
                                     ByVal useShortlabels As Boolean) As BetterArray

Determines the category name from the variable's control type and control details, then queries the choices collaborator.

Parameters:

Returns: BetterArray. The resolved category list.

Throws:


NormaliseControlType #

normalise-control-type

Strip parenthesised suffixes from a control type string

Signature:

Private Function NormaliseControlType(ByVal controlValue As String) As String

Parameters:

Returns: String. The normalised, lower-cased control type.


ExtractChoiceFormula #

extract-choice-formula

Extract the choice name from a CHOICE_FORMULA(...) control details string

Signature:

Private Function ExtractChoiceFormula(ByVal controlDetails As String) As String

Parameters:

Returns: String. The extracted choice name.


Core accessors

ResolveTranslationScope #

resolve-translation-scope

Query the translations collaborator for a given scope

Signature:

Private Function ResolveTranslationScope(ByVal translationScope As Byte) As ITranslationObject

Parameters:

Returns: ITranslationObject. The resolved translation object.

Throws:


Error handling

ThrowError #

throw-error

Raise a project error with the class name as source

Signature:

Private Sub ThrowError(ByVal errNumber As Long, ByVal messageText As String)

Internal error-raising utility.

Parameters:


Test support

TestAssignDesignerTranslations #

test-assign-designer-translations

Inject a mock IDesignerTranslation instance for testing

Signature:

Public Sub TestAssignDesignerTranslations(ByVal designerTrads As IDesignerTranslation)

Backdoor setters for injecting mock collaborators during testing.

Parameters:


TestAssignTranslations #

test-assign-translations

Inject a mock ILLTranslation instance for testing

Signature:

Public Sub TestAssignTranslations(ByVal translations As ILLTranslation)

Also resets the translation cache to ensure the mock object is used for subsequent TransObject lookups.

Parameters:


Interface implementation

ILinelistSpecs_ResetCaches #

Signature:

Private Sub ILinelistSpecs_ResetCaches()

ILinelistSpecs delegation stubs. Each member forwards to its corresponding public member on the concrete class. No @label tags are needed on delegation stubs.


Used in (18 file(s))