AnalysisOutput

Orchestrates the complete analysis output pipeline for the linelist builder. Given a setup worksheet containing analysis definition ListObjects and an output linelist facade, this class iterates through each analysis scope (normal, time series, spatial, spatio-temporal), builds cross-tables from table specifications, writes formulas, registers metadata in AnaTabIds, and renders charts. Consumers interact through the IAnalysisOutput interface.

Depends on: ILinelist, ILinelistSpecs, ILLFormat, ITranslationObject, ITableSpecs, ICrossTable, ICrossTableFormula, IGraphSpecs, IGraphs, IAnaTabIds, IButtons, IPasswords, IDropdownLists, ILLdictionary, ILLVariables, IFormulaData, BetterArray, ListObject names in the setup worksheet, Bug #2 fix: GoTo arrays are now local to each scope, not shared instance state., They are passed as parameters to WriteTable and managed per-scope in WriteAnalysis.

Version: 1.0 (2026-02-10)

Instantiation

create #

Create an AnalysisOutput orchestrator bound to a setup worksheet and output linelist.

Signature:

Public Function Create(ByVal specSh As Worksheet, _
                       ByVal ll As ILinelist) As IAnalysisOutput

Factory method that creates a new AnalysisOutput instance tied to the given setup worksheet and output linelist. The setup worksheet contains the ListObjects that define which tables (global summary, univariate, bivariate, time series, spatial, spatio-temporal) should be generated. The linelist is the output workbook facade where analysis sheets will be created and populated. Both parameters are validated before construction.

Parameters:

  • specSh: Worksheet. The setup worksheet containing analysis ListObjects (Tab_global_summary, Tab_Univariate_Analysis, Tab_Bivariate_Analysis, Tab_TimeSeries_Analysis, Tab_Spatial_Analysis, Tab_SpatioTemporal_Analysis).
  • ll: ILinelist. The output linelist workbook facade where analysis sheets will be created.

Returns: IAnalysisOutput. A fully initialised orchestrator instance ready for use.

Throws:

  • InvalidArgument When the specifications worksheet is Nothing.
  • InvalidArgument When the linelist is Nothing.

Orchestration

write-analysis #

Write all analysis tables, formulas, and graphs to the output.

Signature:

Private Sub WriteAnalysis()

Top-level entry point that builds all four analysis output worksheets. Top-level orchestrator that builds all four analysis output worksheets in sequence: (1) Normal (univariate + bivariate + global summary), (2) Time Series, (3) Spatial, and (4) Spatio-Temporal. For each scope the method prepares the sheet (PrepareSheet), allocates fresh local GoTo arrays (Bug #2 fix), calls WriteTable for each relevant setup ListObject, optionally calls graph-creation subs, builds the section-level GoTo dropdown (AddGoTo), re-adds command buttons (AddCommands), password- protects the sheet, and hides it if no tables were written (the RNG_HasTable_* flag is still empty). Application performance mode is enabled once at the top via BusyApp.

Remarks:

  • The normal scope writes three ListObjects (GLOBALSUMMARY, UNIVARIATE, BIVARIATE) in sequence. Time-series and spatio-temporal scopes also create graphs and a graph-level GoTo dropdown. The caller (IAnalysisOutput_WriteAnalysis) is responsible for restoring Application settings after this method returns.

Internal members (not exported)

Internal Properties

self #

Current object instance.

Signature:

Public Property Get Self() As IAnalysisOutput

Properties used during factory construction and internal wiring. Convenience accessor that returns the current instance cast to the IAnalysisOutput interface, enabling the predeclared factory pattern.

Returns: IAnalysisOutput. The current instance cast to the interface.


output-ll-get #

Output linelist facade.

Signature:

Public Property Get OutputLL() As ILinelist

Returns the ILinelist reference representing the output workbook where analysis worksheets are created and populated.

Returns: ILinelist. The output linelist workbook facade.


output-ll-set #

Assign the output linelist facade.

Signature:

Public Property Set OutputLL(ByVal ll As ILinelist)

Parameters:


wksh-get #

Setup worksheet reference.

Signature:

Public Property Get Wksh() As Worksheet

Returns the setup worksheet containing analysis definition ListObjects.

Returns: Worksheet. The setup worksheet containing analysis ListObjects.


wksh-set #

Assign the setup worksheet reference.

Signature:

Public Property Set Wksh(ByVal specSh As Worksheet)

Parameters:


Dependency Properties

linelist-data #

Linelist metadata facade.

Signature:

Private Property Get LinelistData() As ILinelistSpecs

Convenience accessors for frequently used collaborators retrieved through the output linelist and its metadata facade. Convenience accessor that retrieves the ILinelistSpecs object from the stored output linelist. ILinelistSpecs is the central metadata facade providing access to the dictionary, translation objects, formula data, design format, passwords, and sheet configuration. This property avoids repeating OutputLL().LinelistData() throughout the class.

Returns: ILinelistSpecs. Metadata facade for the output linelist.


design-format #

Design format object.

Signature:

Private Property Get DesignFormat() As ILLFormat

Convenience accessor for the ILLFormat design format object used to apply visual formatting (fonts, colours, borders, cell styles) to analysis worksheets, cells, and chart elements. Delegates through LinelistData to retrieve the shared format singleton so all analysis output uses consistent styling from the setup workbook.

Returns: ILLFormat. Design format object for the output linelist.


trans-object #

Translation object for a given scope.

Signature:

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

Retrieves an ITranslationObject for the requested translation scope. Translation objects resolve human-readable labels, button captions, sheet names, and other locale-dependent strings from the setup workbook. The scope parameter controls which translation table is used: messages (default), shape names, or other categories defined by the TranslationScope enum.

Parameters:

Returns: ITranslationObject. Bound to the requested translation scope.


output-sh #

Output worksheet for a given analysis scope.

Signature:

Private Property Get OutputSh(Optional ByVal scope As Byte = AnalysisScopeNormal) As Worksheet

Resolves the output worksheet in the linelist workbook for the given analysis scope. Each scope maps to a translated sheet name stored in the messages translation table (e.g. "LLSHEET_Analysis" for normal, "LLSHEET_TemporalAnalysis" for time series). The translation ensures the output sheet names match the user's configured language.

Parameters:

Returns: Worksheet. The output analysis sheet in the linelist workbook.


names-object #

Lazily-initialised analysis tracking object.

Signature:

Private Property Get NamesObject() As IAnaTabIds

Lazily-initialised accessor for the IAnaTabIds tracking object. AnaTabIds maintains a registry of all cross-table named ranges and graph metadata created during the analysis build. This registry is later used by the update/filter commands to locate tables and graphs at runtime. The object is created once on first access using the temporary analysis worksheet from the linelist, and all subsequent calls return the cached instance.

Returns: IAnaTabIds. Tracking object that records table and graph metadata.

Remarks:


Application Helpers

busy-app #

Suppress Excel visual feedback and recalculation for performance.

Signature:

Private Sub BusyApp()

Disables ScreenUpdating, DisplayAlerts, Calculation (switches to manual), and EnableAnimations on the Application object to maximise performance during batch write operations. These settings are restored externally after the full analysis build completes.

Remarks:


split-output-sheet #

Apply freeze-pane split to an analysis output worksheet.

Signature:

Private Sub SplitOutputSheet(Optional ByVal scope As Byte = AnalysisScopeNormal)

Applies a freeze-pane split to the output analysis worksheet so that header rows and the left navigation columns remain visible while the user scrolls through tables. The row split is 2 for normal/spatial scopes and 3 for time-series and spatio-temporal scopes (which have an extra GoTo-header dropdown row). The column split is always 3. Zoom is set to 80% for a wider view of cross-tables.

Parameters:

Remarks:


Sheet Preparation

add-commands #

Add a filter/update command button to the analysis output worksheet.

Signature:

Private Sub AddCommands(Optional ByVal scope As Byte = AnalysisScopeNormal)

Places a command button on the output worksheet that triggers either the standard filter-update macro (UPDATEFILTERCOMMAND) or the spatial-specific update macro (UPDATESPCOMMAND) depending on the scope. The button is placed at row 2 col 2, styled using the design format, and labelled with the translated SHP_Filter shape name. Exits early when the linelist is built from a template (mainobj.HasTemplate), because the template already contains the buttons.

Parameters:


prepare-sheet #

Perform five-step initialisation of an analysis output worksheet.

Signature:

Private Sub PrepareSheet(Optional ByVal scope As Byte = AnalysisScopeNormal)

Initialises an analysis output worksheet before any tables are written. The five steps are: (1) write a scope-specific flag named range at row 1 col 10 (e.g. RNG_HasTable_UNI), formatted as a hidden cell; (2) apply the AllAnalysisSheet base format to the entire worksheet; (3) write a sheet-info identifier at row 1 col 3 as a hidden cell; (4) place the ComputedOnFiltered() warning formula at row 2 col 5 with LinelistWarning formatting; (5) delegate to AddCommands and SplitOutputSheet for button and freeze-pane setup.

Parameters:


GoTo Dropdown Helpers

add-goto #

Create a data-validation dropdown for section/graph navigation.

Signature:

Private Sub AddGoTo(ByVal cellRng As Range, _
                    ByVal dropArray As BetterArray, _
                    ByVal goToLabel As String, _
                    Optional ByVal goToPrefix As String = "ua_", _
                    Optional ByVal goToSuffix As String = vbNullString)

Creates a data-validation dropdown in a single cell that lets the user navigate to a named section, header, or graph on the analysis sheet. The entries in dropArray become the validation list; selecting one triggers a GoTo macro that scrolls to the corresponding named range. The cell is formatted as a LinelistSelectionDropdown, its initial value is set to goToLabel, and it receives a workbook-level named range. If dropArray is empty the method exits silently so callers do not need to guard.

Parameters:


Temporal Section Helpers

min-max-formula #

Finalise temporal section date-period boundary formulas and GoTo header dropdown.

Signature:

Private Sub MinMaxFormula(ByVal outsh As Worksheet, ByVal secId As String, _
                          ByVal minFormula As String, ByVal maxFormula As String, _
                          ByVal goToPrefix As String, _
                          ByVal headersList As BetterArray, _
                          ByVal goToHeaderLabel As String)

Min/Max formula finalisation and GoTo header dropdown for temporal sections. Finalises a temporal (time-series or spatio-temporal) section by writing its date-period boundary formulas and adding a GoTo Header dropdown. Each temporal section has two named ranges: MIN_MIN_DATE_{secId} and MAX_MAX_DATE_{secId}, which hold the overall minimum and maximum dates across all tables in that section. The minFormula and maxFormula strings are comma-separated MIN/MAX fragments accumulated by WriteTable; this method wraps them in a final worksheet formula. After writing, a GoTo Header dropdown is placed two rows below the SECTION_{secId} named range.

Parameters:


Table Creation

write-table #

Iterate setup ListObject rows and build cross-tables on the output sheet.

Signature:

Private Sub WriteTable(ByVal loName As String, _
                       ByVal sectionsList As BetterArray, _
                       ByVal headersList As BetterArray, _
                       Optional ByVal scope As Byte = AnalysisScopeNormal)

Core table-creation loop and supporting write logic. Core table-creation loop. Iterates over every data row of the setup ListObject identified by loName, and for each valid row: creates a TableSpecs, builds a CrossTable on the output sheet, applies CrossTableFormula formulas, formats the table with the design, registers the table's named ranges in the AnaTabIds tracking object, and optionally creates a chart (GraphSpecs + Graphs). For time-series and spatio-temporal scopes, additional logic accumulates MIN/MAX date formulas per section and writes them via MinMaxFormula when a section boundary is detected. GoTo section and header entries are pushed into the caller-provided sectionsList and headersList arrays. Each table is wrapped in a per-table error handler (Bug #3 fix) so that a single malformed row does not abort the entire analysis; errors are logged to the Immediate window.

Parameters:

Remarks:


Graph Creation

write-time-series-graphs #

Build all time-series charts from the graph definition ListObjects.

Signature:

Private Sub WriteTimeSeriesGraphs(ByVal graphLoName As String, _
                                   ByVal graphTitleLoName As String, _
                                   ByVal tabLoName As String, _
                                   ByVal graphsList As BetterArray)

Methods that build time-series and spatio-temporal charts after tables have been written. Reads three setup ListObjects: the graph definition table (graphLoName), the graph title/label table (graphTitleLoName), and the original time-series table (tabLoName). These are bundled into a BetterArray and passed to GraphSpecs.CreateRangeSpecs, which operates in complex mode -- resolving multi-series graphs with mixed chart types and separate axis positions. The method then loops over each graph, creates it via Graphs.Create, iterates its series to add data ranges and labels, formats the chart, records metadata in AnaTabIds, and advances the anchor cell by 50 rows. Finally, a GoTo graph dropdown is placed at row 3 col 3.

Parameters:

Remarks:


write-spatio-temporal-graph #

Build spatio-temporal charts from the table definition ListObject.

Signature:

Private Sub WriteSpatioTemporalGraph(ByVal loName As String, _
                                      ByVal graphsList As BetterArray)

Builds spatio-temporal charts by re-reading the same setup ListObject that was used to create the spatio-temporal tables (loName). Unlike WriteTimeSeriesGraphs which uses a separate graph-definition ListObject, this method iterates over the original table rows, checks HasGraph for each, and creates one chart per qualifying table using the simpler GraphSpecs.Create (non-complex) mode. Each graph's plot title is composed from the translated "MSG_Graph" label plus the STARTCOL named-range value. Charts are spaced 50 rows apart. After all charts are created, a GoTo graph dropdown is placed at row 3 col 3.

Parameters:

Remarks:


Error Handling

throw-error #

Raise a project error with standardised source.

Signature:

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

Wrapper around Err.Raise that standardises the source to CLASS_NAME, providing a consistent stack trace across all methods in this class.

Parameters:

Throws:


Interface Implementation

IAnalysisOutput_WriteAnalysis #

Signature:

Private Sub IAnalysisOutput_WriteAnalysis()

Delegated members satisfying the IAnalysisOutput contract. See the corresponding Public/Private members above for full documentation.


Used in (3 file(s))