Development
The Development class is the central orchestrator for workbook development workflows in OutbreakTools. It manages code tables (ListObjects that list VBA classes, modules, forms, and tests), drives bulk import and export of code artefacts between disk and the host workbook VBProject, and executes deployment by protecting and hiding registered worksheets. Consumers interact through the IDevelopment interface using the predeclared factory pattern (Development.Create).
Depends on: BetterArray, IPasswords
Version: 1.0 (2026-02-09)
Factory
create #
Create a Development instance.
Signature:
Public Function Create(ByVal devSheet As Worksheet, Optional ByVal codeSheet As Worksheet) As IDevelopment
Predeclared factory entry point for creating Development instances. Factory method on the predeclared instance that allocates a new Development object and binds it to the supplied Dev worksheet via Initialise. When a codeSheet is provided, it is registered as the target for new development tables. The returned object is cast to the IDevelopment interface so consumers program against the contract rather than the concrete class.
Parameters:
devSheet: Worksheet. The worksheet hosting development named ranges such as module and class folder paths.codeSheet: Optional Worksheet. A separate worksheet to host code ListObjects. When omitted, tables are placed on devSheet.
Returns: IDevelopment. A fully initialised instance ready for use.
Throws:
- ProjectError.ObjectNotInitialized When devSheet is Nothing.
- ProjectError.ElementNotFound When required named ranges are missing on the Dev worksheet.
Depends on:
- BetterArray
Internal members (not exported)
Initialisation
initialise #
Bind this instance to a Dev worksheet and optional code sheet.
Signature:
Public Sub Initialise(ByVal devSheet As Worksheet, Optional ByVal codeSheet As Worksheet)
Instance setup that binds internal state to the host workbook. Validates that devSheet is not Nothing, stores the worksheet and its parent workbook, enables user confirmation prompts, and initialises the hidden and protected sheet collections. Required named ranges for module and class folder paths are verified on the Dev sheet. Any previously registered code worksheet is restored from a persisted worksheet-level name. When a codeSheet argument is supplied, it replaces the restored worksheet.
Parameters:
devSheet: Worksheet. The development worksheet carrying configuration named ranges.codeSheet: Optional Worksheet. A worksheet to register as the code table host. When omitted, any previously persisted code worksheet is used.
Throws:
- ProjectError.ObjectNotInitialized When devSheet is Nothing.
- ProjectError.ElementNotFound When required named ranges are missing.
Sheet Preparation API
add-code-sheets #
Register an existing worksheet to host future development tables.
Signature:
Public Function AddCodeSheets(ByVal sheetName As String) As Worksheet
Public methods for registering worksheets and creating development tables (classes, modules, forms, tests). Validates that the supplied name is non-empty and that the worksheet exists in the host workbook. When user prompts are enabled, a confirmation dialog is displayed before proceeding. The registered worksheet is persisted via a worksheet-level named range so it survives workbook close/reopen cycles. ("Register an existing worksheet so future tables are created on it.")
Parameters:
sheetName: String. Name of the worksheet to register as the code table host.
Returns: Worksheet. The registered worksheet reference, or Nothing when the user declines the confirmation prompt.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.InvalidArgument When sheetName is empty.
- ProjectError.ElementNotFound When the worksheet does not exist in the host workbook.
add-class-table #
Create a classes table on the code worksheet.
Signature:
Public Function AddClassTable(Optional ByVal includeTests As Boolean = False) As ListObject
Creates a new ListObject with columns for class names and an interface Yes/No flag. The includeTests parameter switches the table tag between "general classes" and "tests classes", which determines the destination folder during code transfers. A confirmation dialog is shown when prompts are enabled. The table is placed at the next available horizontal anchor on the code worksheet (or the Dev sheet when no code worksheet is registered). ("Create a classes table, optionally scoped to tests.")
Parameters:
includeTests: Optional Boolean. When True, creates a test-scoped classes table. Defaults to False.
Returns: ListObject. The newly created table, or Nothing when the user declines the confirmation prompt.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
add-module-table #
Create a modules table on the code worksheet.
Signature:
Public Function AddModuleTable(Optional ByVal includeTests As Boolean = False) As ListObject
Creates a new ListObject with a single column for module names. The includeTests parameter switches the table tag between "general modules" and "tests modules", controlling the destination folder during transfers. A confirmation dialog is shown when prompts are enabled. ("Create a modules table, optionally scoped to tests.")
Parameters:
includeTests: Optional Boolean. When True, creates a test-scoped modules table. Defaults to False.
Returns: ListObject. The newly created table, or Nothing when the user declines the confirmation prompt.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
add-forms-table #
Create a forms mapping table on the code worksheet.
Signature:
Public Function AddFormsTable() As ListObject
Creates a new ListObject with two columns: "modules" and "corresponding form". Entries in this table drive the AddFormsCodes and Deploy workflows, which copy code from a standard module into the code-behind of a UserForm component. A confirmation dialog is shown when prompts are enabled. ("Create a forms mapping table used for code transfers to userforms.")
Returns: ListObject. The newly created table, or Nothing when the user declines the confirmation prompt.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
add-test-table #
Create a test modules table on the code worksheet.
Signature:
Public Function AddTestTable() As ListObject
Creates a new ListObject configured for test module entries with a single "modules" column. The table is tagged as "tests modules" so that code transfers target the tests folder. A confirmation dialog is shown when prompts are enabled. ("Create a test modules table for organising test imports/exports.")
Returns: ListObject. The newly created table, or Nothing when the user declines the confirmation prompt.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
Deployment Configuration
add-hidden-sheet #
Track a worksheet that must be hidden during deployment.
Signature:
Public Sub AddHiddenSheet(ByVal sheetName As String)
Methods for registering worksheets that must be hidden or protected when the workbook is deployed. Appends the supplied worksheet name to the internal hiddenSheets collection. During Deploy, every entry in this collection is set to xlSheetVeryHidden. The worksheet must exist in the host workbook. ("Track a worksheet that must be hidden during deployment.")
Parameters:
sheetName: String. Name of the worksheet to hide during deployment.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.InvalidArgument When sheetName is empty.
- ProjectError.ElementNotFound When the worksheet does not exist.
add-protected-sheet #
Track a worksheet that needs protection during deployment.
Signature:
Public Sub AddProtectedSheet(ByVal sheetName As String, _
Optional ByVal allowShapes As Boolean = True, _
Optional ByVal allowDeletingRows As Boolean = True)
Registers a worksheet by name so that it will be protected when Deploy is called. The optional parameters control whether shapes and row deletion are permitted on the protected sheet. The registration is stored as a BetterArray triplet (name, allowShapes, allowDeletingRows) inside the protectedSheets collection. ("Track a worksheet that needs to be protected during deployment.")
Parameters:
sheetName: String. Name of the worksheet to protect during deployment.allowShapes: Optional Boolean. When True, shapes remain editable on the protected sheet. Defaults to True.allowDeletingRows: Optional Boolean. When True, row deletion is allowed on the protected sheet. Defaults to True.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.InvalidArgument When sheetName is empty.
- ProjectError.ElementNotFound When the worksheet does not exist.
Code Transfer
import-all #
Import every module and class listed in Dev tables into the host workbook.
Signature:
Public Sub ImportAll()
Bulk import and export of VBA components listed in development tables. Iterates every ListObject on the Dev sheet and any registered code worksheet. Each table tag is read to determine the transfer scope (modules or classes) and the target disk folder. For each entry in the table, the corresponding .bas or .cls file is imported from disk into the host workbook VBProject, replacing any existing component of the same name. A timestamped status message is written to the Dev sheet Informations range upon completion. Requires that host sheets are unlocked. ("Import every module/class listed in Dev tables into this workbook.")
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.ErrorUnexpectedState When a host sheet is protected.
export-all #
Export every module and class listed in Dev tables to disk.
Signature:
Public Sub ExportAll()
Iterates every ListObject on the Dev sheet and any registered code worksheet. Each table tag is read to determine the transfer scope and the source disk folder. For each entry, the VBA component is exported from the host workbook VBProject to disk, overwriting any existing file. A timestamped status message is written upon completion. Requires that host sheets are unlocked. ("Export every module/class listed in Dev tables to disk.")
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.ErrorUnexpectedState When a host sheet is protected.
add-forms-codes #
Copy module code into mapped UserForm components.
Signature:
Public Sub AddFormsCodes()
Synchronises form modules by copying the code from each source module listed in forms tables into the corresponding UserForm component. A confirmation dialog is shown when prompts are enabled. After copying, the source module is removed from the VBProject to prevent duplication. Requires that host sheets are unlocked. ("Copy module code into mapped forms according to the forms table.")
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
- ProjectError.ErrorUnexpectedState When a host sheet is protected.
Deployment
deploy #
Protect worksheets, hide Dev assets, copy forms code, and set the deployment marker.
Signature:
Public Sub Deploy(ByVal pass As IPasswords, Optional ByVal lockWorkbook As Boolean = False)
Full deployment workflow: protect, hide, and lock the workbook. Executes the full deployment workflow. First applies the default password from the Dev sheet, then synchronises form modules without confirmation. Every worksheet registered via AddHiddenSheet is set to xlSheetVeryHidden. Every worksheet registered via AddProtectedSheet is protected using the supplied IPasswords handler with the recorded permission flags. When lockWorkbook is True, the host workbook itself is locked. The code worksheet (if distinct from the Dev sheet) is hidden. Finally, a debug exit handler is installed and the workbook-level deployment flag is set to "Yes". ("Protect worksheets, hide Dev assets, copy forms code, and set deployment marker.")
Parameters:
pass: IPasswords. The password handler used to apply protection to worksheets and optionally lock the workbook.lockWorkbook: Optional Boolean. When True, the host workbook structure is locked after protecting sheets. Defaults to False.
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called or when pass is Nothing.
- ProjectError.ErrorUnexpectedState When a host sheet is protected.
in-deployment #
Check whether the workbook has already been deployed.
Signature:
Public Function InDeployment() As Boolean
Reads the workbook-level named range "inDeployment" and performs a case-insensitive comparison against "Yes". Returns True when the stored value matches, indicating that Deploy has already been executed. Returns False when the name does not exist or contains any other value. ("Return True when the workbook has already been deployed (flag equals 'Yes').")
Returns: Boolean. True when the deployment flag equals "Yes".
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
Properties
dev-worksheet #
Development worksheet reference.
Signature:
Public Property Get DevWorksheet() As Worksheet
Read-only and read-write properties exposing the internal state. Returns the Dev worksheet that stores configuration named ranges such as folder paths and counter values. Set during Initialise and never changed afterwards. ("Development worksheet storing configuration named ranges.")
Returns: Worksheet. The development worksheet bound to this instance.
code-worksheet #
Worksheet registered to host development tables.
Signature:
Public Property Get CodeWorksheet() As Worksheet
Returns the worksheet currently registered to host development ListObjects. May be Nothing when no code worksheet has been registered, in which case new tables are created on the Dev sheet itself. ("Worksheet currently registered to host development tables (may be Dev sheet).")
Returns: Worksheet. The code worksheet, or Nothing when none is registered.
display-prompts #
Whether confirmation prompts are displayed.
Signature:
Public Property Get DisplayPrompts() As Boolean
Controls whether confirmation dialogs are shown before mutating operations such as importing, exporting, or adding tables. Defaults to True after Initialise. Set to False to suppress prompts during automated or batch workflows. ("Whether user confirmation prompts are displayed before mutating operations.")
Returns: Boolean. True when prompts are enabled.
display-prompts-set #
Set the confirmation prompt toggle.
Signature:
Public Property Let DisplayPrompts(ByVal value As Boolean)
Parameters:
value: Boolean. True to enable prompts, False to suppress them.
Worksheet Helpers
ensure-collections #
Initialise sheet tracking collections when not yet allocated.
Signature:
Private Sub EnsureCollections()
Private helpers that manage worksheet discovery, validation, and collection initialisation. ("Initialise sheet tracking collections for hidden/protected lists.")
ensure-named-ranges #
Validate that required Dev sheet named ranges exist.
Signature:
Private Sub EnsureNamedRanges()
Checks that the module and class folder named ranges are present on the Dev sheet. The tests folder range is optional and is only validated when its name definition already exists at the workbook level. ("Validate Dev sheet named ranges for module/class/test folders.")
Throws:
- ProjectError.ElementNotFound When a required named range is missing.
restore-code-worksheet #
Restore a previously registered code worksheet from persisted state.
Signature:
Private Sub RestoreCodeWorksheet()
Reads the worksheet-level named range CODE_SHEET_NAMEDEF. When a valid sheet name is found and the worksheet exists, it is set as the active code worksheet. Silently exits when no persisted name exists. ("Restore previously registered code worksheet if stored.")
ensure-worksheet #
Resolve a worksheet by name, raising on empty name or missing sheet.
Signature:
Private Function EnsureWorksheet(ByVal sheetName As String, ByVal purpose As String) As Worksheet
Trims the supplied name and attempts to resolve it in the host workbook. Raises InvalidArgument when the name is empty and ElementNotFound when no matching worksheet exists. The purpose parameter is included in error messages to help callers identify the context.
Parameters:
sheetName: String. Name of the worksheet to resolve.purpose: String. Label included in error messages for context.
Returns: Worksheet. The resolved worksheet reference.
Throws:
- ProjectError.InvalidArgument When sheetName is empty.
- ProjectError.ElementNotFound When the worksheet does not exist.
try-resolve-worksheet #
Attempt to resolve a worksheet by name without raising.
Signature:
Private Function TryResolveWorksheet(ByVal sheetName As String) As Worksheet
Parameters:
sheetName: String. Name of the worksheet to look up.
Returns: Worksheet. The resolved worksheet, or Nothing when not found.
ensure-range-exists #
Validate that a named range exists on a worksheet.
Signature:
Private Sub EnsureRangeExists(ByVal sheet As Worksheet, _
ByVal rangeName As String, _
Optional ByVal required As Boolean = True)
("Ensure a named range exists on a worksheet, raising when mandatory.")
Parameters:
sheet: Worksheet. The worksheet to check.rangeName: String. The named range to locate.required: Optional Boolean. When True, raises an error if the range is missing. Defaults to True.
Throws:
- ProjectError.ElementNotFound When required is True and the range is not found.
register-code-worksheet #
Persist a worksheet as the active code table host.
Signature:
Private Sub RegisterCodeWorksheet(ByVal sheetName As String)
("Persist the supplied worksheet as the active code worksheet.")
Parameters:
sheetName: String. Name of the worksheet to register.
resolve-table-host #
Return the worksheet where new tables should be created.
Signature:
Private Function ResolveTableHost() As Worksheet
("Return the worksheet where new development tables should be created.")
Returns: Worksheet. The code worksheet when registered, otherwise the Dev sheet.
table-host-sheets #
Collect worksheets that may contain development tables.
Signature:
Private Function TableHostSheets() As Collection
Returns a Collection containing the Dev sheet and, when registered and distinct, the code worksheet. Used by import/export and form synchronisation routines to iterate all possible table hosts. ("Return worksheets that may contain development tables for processing.")
Returns: Collection. One or two Worksheet references.
ensure-host-sheets-unlocked #
Verify that candidate worksheets are not protected.
Signature:
Private Sub EnsureHostSheetsUnlocked()
Iterates every worksheet returned by TableHostSheets and raises an error when any of them has ProtectContents set to True. This guard prevents import, export, and deployment operations from failing mid-way due to sheet protection. ("Confirm candidate worksheets are unprotected before modification.")
Throws:
- ProjectError.ErrorUnexpectedState When a host sheet is protected.
ensure-initialised #
Guard public API calls when Development has not been initialised.
Signature:
Private Sub EnsureInitialised()
("Guard public API calls when Development has not been initialised.")
Throws:
- ProjectError.ObjectNotInitialized When Initialise has not been called.
Code Transfer Helpers
process-all-tables #
Iterate every development table and dispatch import or export.
Signature:
Private Sub ProcessAllTables(ByVal mode As DevelopmentTransferMode)
Private helpers that drive the import and export of VBA components listed in development tables. Reads folder settings from the Dev sheet, then walks every ListObject on each host worksheet. Each table is passed to ProcessListObject, which interprets the tag above the table to decide scope (modules or classes), target folder, and whether interfaces should be included. ("Iterate every development table and process it for import/export.")
Parameters:
mode: DevelopmentTransferMode. Whether to import or export.
resolve-folder-settings #
Read module, class, and test folder paths from the Dev sheet.
Signature:
Private Function ResolveFolderSettings() As TFolderSettings
("Read module/class/test folder settings from the Dev sheet.")
Returns: TFolderSettings. The resolved folder paths.
read-sheet-value #
Return the trimmed string value of a named range on the Dev sheet.
Signature:
Private Function ReadSheetValue(ByVal rangeName As String, Optional ByVal required As Boolean = True) As String
Locates the named range by first checking worksheet-level names, then falling back to workbook-level names. When the range cannot be resolved and required is True, an error is raised. Returns an empty string when the range is missing and required is False. ("Return the string value of a named range, enforcing presence when required.")
Parameters:
rangeName: String. The named range to read.required: Optional Boolean. When True, raises an error if the range is missing. Defaults to True.
Returns: String. The trimmed cell value, or empty string when not found.
Throws:
- ProjectError.ElementNotFound When required is True and the range is missing.
process-list-object #
Process a single ListObject for import or export.
Signature:
Private Function ProcessListObject(ByVal lo As ListObject, _
ByVal mode As DevelopmentTransferMode, _
ByRef folders As TFolderSettings) As Boolean
Reads the tag cell above the table to determine the scope (modules, classes, tests, or forms) and the base folder. Reads the folder cell two rows above the table to determine the subfolder. Combines both paths and verifies the directory exists on disk. Delegates to TransferListEntries for actual component-by-component processing. Forms-tagged tables are skipped here (handled by SynchroniseFormsTables instead). Returns True when at least one component was transferred. ("Process a single ListObject, importing or exporting its entries.")
Parameters:
lo: ListObject. The development table to process.mode: DevelopmentTransferMode. Whether to import or export.folders: TFolderSettings. The resolved folder paths.
Returns: Boolean. True when at least one entry was processed.
list-tag #
Retrieve the scope tag stored in the cell above the table.
Signature:
Private Function ListTag(ByVal lo As ListObject) As String
("Retrieve the tag stored above the table (scope identifier).")
Parameters:
lo: ListObject. The target table.
Returns: String. The trimmed tag value, or empty string when absent.
compare-tag #
Case-insensitive comparison between a table tag and an expected value.
Signature:
Private Function CompareTag(ByVal lo As ListObject, ByVal expected As String) As Boolean
("Case-insensitive comparison between a table tag and expected text.")
Parameters:
lo: ListObject. The table whose tag is compared.expected: String. The expected tag text.
Returns: Boolean. True when the tags match.
list-folder #
Retrieve the subfolder path stored two rows above the table.
Signature:
Private Function ListFolder(ByVal lo As ListObject) As String
("Retrieve the folder path written above the table (relative folder).")
Parameters:
lo: ListObject. The target table.
Returns: String. The trimmed subfolder path, or empty string when absent.
append-path #
Combine a base path and subpath using the platform separator.
Signature:
Private Function AppendPath(ByVal basePath As String, ByVal subPath As String) As String
("Combine base and sub-path using the platform path separator.")
Parameters:
basePath: String. The root folder path.subPath: String. The relative subfolder to append.
Returns: String. The combined path.
directory-exists #
Return True when the supplied directory exists on disk.
Signature:
Private Function DirectoryExists(ByVal pathValue As String) As Boolean
("Return True when the supplied directory exists on disk.")
Parameters:
pathValue: String. The directory path to check.
Returns: Boolean. True when the directory exists.
transfer-list-entries #
Iterate table rows and import or export each listed component.
Signature:
Private Function TransferListEntries(ByVal lo As ListObject, _
ByVal destinationFolder As String, _
ByVal scope As DevelopmentTransferScope, _
ByVal mode As DevelopmentTransferMode, _
ByVal includeInterface As Boolean) As Boolean
Reads the first column for component names and, when includeInterface is True, the second column for a Yes/No interface flag. For each non-empty entry the component is transferred via TransferComponent. When the flag is "yes", the corresponding interface file (prefixed with "I") is also transferred. Returns True when at least one component was processed. ("Iterate table rows and import/export each listed component.")
Parameters:
lo: ListObject. The development table containing component entries.destinationFolder: String. The disk folder for the transfer.scope: DevelopmentTransferScope. Whether entries are modules or classes.mode: DevelopmentTransferMode. Whether to import or export.includeInterface: Boolean. When True, also transfer interface files.
Returns: Boolean. True when at least one entry was transferred.
resolve-interface-flag #
Read the Yes/No interface flag for a given table row.
Signature:
Private Function ResolveInterfaceFlag(ByVal interfaceColumn As Range, ByVal rowIndex As Long) As String
("Return lowercase 'yes'/'no' flag for interface duplication, handling missing cells.")
Parameters:
interfaceColumn: Range. The second column range, or Nothing.rowIndex: Long. The 1-based row index within the column.
Returns: String. Lowercase "yes" or "no", or empty string when unavailable.
transfer-component #
Build the file path and delegate to import or export.
Signature:
Private Sub TransferComponent(ByVal componentName As String, _
ByVal destinationFolder As String, _
ByVal scope As DevelopmentTransferScope, _
ByVal mode As DevelopmentTransferMode)
("Import or export a single component based on mode and scope.")
Parameters:
componentName: String. The VBA component name.destinationFolder: String. The disk folder for the transfer.scope: DevelopmentTransferScope. Determines the file extension.mode: DevelopmentTransferMode. Whether to import or export.
import-component #
Import a VBA component from disk, replacing any existing one.
Signature:
Private Sub ImportComponent(ByVal componentName As String, ByVal filePath As String)
Checks that the file exists on disk, then removes any existing component with the same name from the VBProject so that VB attributes are refreshed on import. Delegates to VBComponents.Import to perform the actual import. ("Import a code component from disk, replacing any existing component.")
Parameters:
componentName: String. The VBA component name to replace.filePath: String. The full disk path of the .bas or .cls file.
export-component #
Export a VBA component to disk, overwriting any previous file.
Signature:
Private Sub ExportComponent(ByVal componentName As String, ByVal filePath As String)
Looks up the component in the VBProject. When found, deletes any existing file at the target path and exports the component. Silently exits when the component does not exist in the project. ("Export a code component to disk, overwriting any previous file.")
Parameters:
componentName: String. The VBA component name to export.filePath: String. The full disk path for the exported file.
append-information-log #
Append a timestamped entry describing the transfer action performed.
Signature:
Private Sub AppendInformationLog(ByVal targetPath As String, _
ByVal scope As DevelopmentTransferScope, _
ByVal mode As DevelopmentTransferMode)
("Append a timestamped entry describing the import/export action performed.")
Parameters:
targetPath: String. The folder path that was processed.scope: DevelopmentTransferScope. Whether modules or classes were transferred.mode: DevelopmentTransferMode. Whether an import or export was performed.
write-information #
Write a status message to the Dev sheet Informations cell.
Signature:
Private Sub WriteInformation(ByVal messageText As String)
("Write a status message in the Dev sheet informations cell.")
Parameters:
messageText: String. The message to display.
ensure-information-cell #
Locate the Dev sheet status cell from the Informations named range.
Signature:
Private Function EnsureInformationCell() As Range
("Locate the Dev sheet status cell (Informations named range).")
Returns: Range. The target cell, or Nothing when the range is not defined.
Form Synchronisation
synchronise-forms-tables #
Enumerate forms tables and copy code into mapped UserForm components.
Signature:
Private Sub SynchroniseFormsTables(ByVal requireConfirmation As Boolean)
Private helpers that copy code from standard modules into UserForm components based on forms tables. Walks every ListObject on each host worksheet and identifies those tagged as "general form modules". For each matching table, ProcessFormsTable is called to copy module code into the corresponding form component. When requireConfirmation is True, a dialog is shown before proceeding. ("Enumerate all forms tables and optionally prompt before synchronising code.")
Parameters:
requireConfirmation: Boolean. When True, prompts the user first.
apply-default-password #
Read and apply the default password from the Dev sheet.
Signature:
Private Sub ApplyDefaultPassword(ByVal passwords As IPasswords)
Checks for a named range "DefaultPassword" on the Dev sheet. When found and non-empty, passes its value to the IPasswords handler via NewDebugingPassword. Silently exits when no default password is configured.
Parameters:
passwords: IPasswords. The password handler to configure.
process-forms-table #
Copy code for each module/form pair defined in a forms ListObject.
Signature:
Private Sub ProcessFormsTable(ByVal lo As ListObject)
Reads the first column for source module names and the second column for target form names. For each non-empty pair, CopyModuleCode transfers the code from the module into the form component and removes the source. ("Copy code for each module/form pair defined in the supplied ListObject.")
Parameters:
lo: ListObject. The forms mapping table to process.
copy-module-code #
Copy the VBIDE code from one component into another.
Signature:
Private Sub CopyModuleCode(ByVal sourceName As String, ByVal targetName As String)
Reads all lines from the source component CodeModule, clears the target component CodeModule, and writes the source content into it. The source component is then removed from the VBProject. Raises ElementNotFound when either the source or target component does not exist. ("Copy the VBIDE code from one component into another.")
Parameters:
sourceName: String. Name of the VBA component to copy from.targetName: String. Name of the VBA component to copy into.
Throws:
- ProjectError.ElementNotFound When the source or target component is not found in the VBProject.
ListObject Builders
create-list-object #
Create a table with standardised headers, tag, and naming.
Signature:
Private Function CreateListObject(ByVal headers As Variant, _
ByVal tagValue As String, _
ByVal counterName As String, _
ByVal prefix As String, _
Optional ByVal addYesNoValidation As Boolean = False) As ListObject
Private helpers that create, format, and name development tables on the code worksheet. Resolves the host worksheet, calculates the next available horizontal anchor, writes the folder and tag cells above the table, creates a ListObject from a two-row range (header + one data row), applies project formatting, generates a unique name via the persisted counter, and optionally adds Yes/No data validation to the second column. ("Create a table with the supplied headers, tag, and standardised naming.")
Parameters:
headers: Variant. Array of column header strings.tagValue: String. The scope tag written above the table.counterName: String. The worksheet-level name storing the counter.prefix: String. The prefix for the generated ListObject name.addYesNoValidation: Optional Boolean. When True, applies a Yes/No dropdown to the second column. Defaults to False.
Returns: ListObject. The newly created and formatted table.
apply-lo-format #
Apply project formatting to a development ListObject.
Signature:
Private Sub ApplyLoFormat(ByVal Lo As Listobject)
Parameters:
Lo: ListObject. The table to format.
write-headers #
Populate a table header row with the provided field names.
Signature:
Private Sub WriteHeaders(ByVal lo As ListObject, ByVal headers As Variant)
("Populate table header row with provided field names.")
Parameters:
lo: ListObject. The table whose headers are written.headers: Variant. Array of header strings.
apply-yes-no-validation #
Apply a Yes/No dropdown validation to the second column.
Signature:
Private Sub ApplyYesNoValidation(ByVal lo As ListObject)
("Apply Yes/No validation to the second column when applicable.")
Parameters:
lo: ListObject. The table to configure.
next-anchor-range #
Find the next available anchor position for a table.
Signature:
Private Function NextAnchorRange(ByVal sheet As Worksheet, ByVal columnCount As Long) As Range
Scans existing ListObjects and occupied cells on the header row to find the rightmost occupied column. The anchor is placed two columns to the right of this boundary. When the sheet lacks sufficient columns for the requested table width, an error is raised. ("Find the next available anchor position for a table, growing to the right.")
Parameters:
sheet: Worksheet. The worksheet to scan.columnCount: Long. Number of columns needed for the new table.
Returns: Range. The top-left anchor cell for the new table.
Throws:
- ProjectError.ErrorUnexpectedState When there is not enough space.
next-list-object-name #
Generate a unique ListObject name using the persisted counter.
Signature:
Private Function NextListObjectName(ByVal sheet As Worksheet, _
ByVal prefix As String, _
ByVal counterName As String) As String
("Generate a unique ListObject name using the persisted counter.")
Parameters:
sheet: Worksheet. The worksheet hosting the table.prefix: String. The name prefix (e.g. "ClassesLo").counterName: String. The worksheet-level name storing the counter.
Returns: String. A unique name such as "ClassesLo3".
has-list-object #
Check whether a worksheet already defines a ListObject with the given name.
Signature:
Private Function HasListObject(ByVal sheet As Worksheet, ByVal listName As String) As Boolean
("Check whether the worksheet already defines a ListObject with the given name.")
Parameters:
sheet: Worksheet. The worksheet to search.listName: String. The ListObject name to look for.
Returns: Boolean. True when a matching ListObject exists.
Counter Helpers
read-counter #
Read the persisted numeric counter stored as a worksheet name.
Signature:
Private Function ReadCounter(ByVal nameId As String) As Long
Private helpers that read and write persisted numeric counters stored as worksheet-level names. ("Read the persisted numeric counter stored as a worksheet name.")
Parameters:
nameId: String. The name definition identifier.
Returns: Long. The current counter value, or 0 when not found.
update-counter #
Persist the next counter value back to the Dev sheet.
Signature:
Private Sub UpdateCounter(ByVal nameId As String, ByVal value As Long)
("Persist the next counter value back to the Dev sheet.")
Parameters:
nameId: String. The name definition identifier.value: Long. The counter value to store.
sheet-name-definition #
Locate a worksheet-level name definition matching the supplied id.
Signature:
Private Function SheetNameDefinition(ByVal nameId As String) As Name
("Locate a worksheet-level name definition matching the supplied id.")
Parameters:
nameId: String. The name to look up (ignoring sheet prefix).
Returns: Name. The matching definition, or Nothing when not found.
try-name-definition #
Locate a name definition at worksheet or workbook level.
Signature:
Private Function TryNameDefinition(ByVal nameId As String) As Name
Checks worksheet-level names first via SheetNameDefinition, then falls back to the workbook-level Names collection.
Parameters:
nameId: String. The name to look up.
Returns: Name. The matching definition, or Nothing when not found.
assign-sheet-name #
Assign or replace a worksheet-level name with the supplied formula.
Signature:
Private Sub AssignSheetName(ByVal nameId As String, ByVal refersTo As String)
("Assign or replace a worksheet-level name with the supplied formula.")
Parameters:
nameId: String. The name definition identifier.refersTo: String. The formula or value to store.
remove-sheet-name #
Remove a worksheet-level name if it already exists.
Signature:
Private Sub RemoveSheetName(ByVal nameId As String)
("Remove a worksheet-level name if it already exists.")
Parameters:
nameId: String. The name definition to delete.
assign-workbook-name #
Create or replace a workbook-level name with the supplied formula.
Signature:
Private Sub AssignWorkbookName(ByVal nameId As String, ByVal refersTo As String)
("Create or replace a workbook-level name with the supplied formula.")
Parameters:
nameId: String. The name definition identifier.refersTo: String. The formula or value to store.
remove-workbook-name #
Delete a workbook-level name when present.
Signature:
Private Sub RemoveWorkbookName(ByVal nameId As String)
("Delete a workbook-level name when present.")
Parameters:
nameId: String. The name definition to delete.
compare-workbook-name #
Case-insensitive comparison for workbook-level names.
Signature:
Private Function CompareWorkbookName(ByVal definition As Name, ByVal targetName As String) As Boolean
("Case-insensitive comparison for workbook-level names.")
Parameters:
definition: Name. The name definition to compare.targetName: String. The expected name string.
Returns: Boolean. True when names match.
compare-name #
Case-insensitive comparison for worksheet-level names, ignoring sheet prefix.
Signature:
Private Function CompareName(ByVal definition As Name, ByVal targetName As String) As Boolean
Worksheet-level names are stored as "SheetName!DefinitionName". This method strips the sheet prefix before comparing. ("Case-insensitive comparison for worksheet-level names, ignoring sheet prefix.")
Parameters:
definition: Name. The name definition to compare.targetName: String. The expected name string (without prefix).
Returns: Boolean. True when names match.
Name Utilities
name-numeric-value #
Convert a name definition to a numeric value.
Signature:
Private Function NameNumericValue(ByVal definition As Name) As Long
Private helpers for encoding, decoding, and reading values from Excel Name definitions. Attempts to parse the RefersTo formula as a number. When the formula is not numeric, falls back to reading the value of the referred range. Returns 0 when neither approach yields a number. ("Convert a name definition to a numeric value, using RefersTo or range value.")
Parameters:
definition: Name. The name definition to read.
Returns: Long. The numeric value, or 0 when not parseable.
name-string-value #
Return the decoded string value stored in a name definition.
Signature:
Private Function NameStringValue(ByVal definition As Name) As String
("Return the string value stored in a name definition.")
Parameters:
definition: Name. The name definition to read.
Returns: String. The decoded plain text value.
encode-name-value #
Encode plain text as a quoted formula suitable for Name.RefersTo.
Signature:
Private Function EncodeNameValue(ByVal value As String) As String
("Encode plain text as a quoted formula suitable for Name.RefersTo.")
Parameters:
value: String. The text to encode.
Returns: String. The encoded formula string (e.g. ="Hello").
decode-name-value #
Decode a Name.RefersTo formula to raw string content.
Signature:
Private Function DecodeNameValue(ByVal refersTo As String) As String
Strips the leading "=" and surrounding double quotes, then unescapes embedded doubled quotes back to single quotes. ("Decode a Name.RefersTo formula to raw string content.")
Parameters:
refersTo: String. The raw Name.Value or Name.RefersTo string.
Returns: String. The decoded plain text.
Registration Helpers
register-sheet #
Register a worksheet name with permission flags in a BetterArray.
Signature:
Private Sub RegisterSheet(ByVal registry As BetterArray, ByVal sheetName As String, _
Optional ByVal allowShape As Boolean = True, _
Optional ByVal allowDeletingRows As Boolean = True)
Private helper for registering worksheet entries into the protected sheets collection. Wraps the sheet name, allowShape, and allowDeletingRows values into a BetterArray triplet and pushes it onto the registry. Used by AddProtectedSheet to build the protectedSheets collection that Deploy iterates during deployment. ("Register a worksheet name in the provided BetterArray if not already tracked.")
Parameters:
registry: BetterArray. The collection to append to.sheetName: String. The worksheet name to register.allowShape: Optional Boolean. Whether shapes remain editable. Defaults to True.allowDeletingRows: Optional Boolean. Whether row deletion is permitted. Defaults to True.
Prompts
request-confirmation #
Display a confirmation dialog when prompts are enabled.
Signature:
Private Function RequestConfirmation(ByVal action As String) As Boolean
User confirmation dialog management. When displayPrompts is False, returns True immediately without showing a dialog. Otherwise displays a Yes/No message box. Returns True only when the user selects Yes. ("Display a confirmation dialog when prompts are enabled.")
Parameters:
action: String. A verb phrase describing the action being confirmed.
Returns: Boolean. True when the user confirms or prompts are disabled.
Error Handling
throw-error #
Raise a ProjectError-based exception with a prefixed message.
Signature:
Private Sub ThrowError(ByVal errNumber As ProjectError, ByVal message As String)
Centralised error-raising helper. ("Raise a project-scoped runtime error with prefixed message.")
Parameters:
errNumber: ProjectError. The error code to raise.message: String. Human-readable description of the failure.
Throws:
- ProjectError.
Always raises the specified error.
Interface Implementation
IDevelopment_Initialise #
Signature:
Private Sub IDevelopment_Initialise(ByVal devSheet As Worksheet, Optional ByVal codeSheet As Worksheet)
Delegated members that satisfy the IDevelopment contract. See the corresponding Public members above for full documentation.