AnalysisOutput
Writes every analysis sheet of a generated linelist. Create takes the setup worksheet that holds the analysis definition ListObjects and the linelist facade the sheets are written into. WriteAnalysis walks each analysis scope -- normal, time series, spatial and spatio-temporal -- builds the cross-tables from their table specifications, writes the formulas, records the chart metadata in AnaTabIds and draws the charts. TransObject answers the translation provider, and entries filed along the way leave through HasCheckings and CheckingValues.
THE CLASS OWNS THE STATE ITS OWN WORK NEEDS
WriteAnalysis opens an ApplicationState of its own, turns screen updating, alerts, automatic calculation, animations and events off for the length of the build, and restores on the way out -- on the error path too. The sheets are therefore written under the state the analysis needs whoever calls it, and a caller that keeps its own scope, which is what clickGenerate does, is not disturbed: the snapshot taken here is the caller's busy state, so restoring puts that back rather than the pre-generation values.
A SECTION IS TOLD TO THE LOOP
The date bounds and the navigation dropdown of a temporal section are held by a TemporalSection. The loop closes the section it holds when it meets a table that starts a new one, and closes the last one after the loop. Nothing reads the row below to decide where a section ends.
Depends on: Linelist, LinelistSpecs, LLFormat, TranslationObject, TableSpecs, CrossTable, CrossTableFormula, Graphs, GraphSeries, TimeSeriesGraphs, SeriesBuffer, AnaTabIds, TemporalSection, ApplicationState, Buttons, Passwords, DropdownLists, HiddenNames, LLdictionary, LLVariables, FormulaData, Checking, BetterArray, ListObject names in the setup worksheet, Checking support
Version: 2026-08-12
Instantiation
Create #
create
Create an AnalysisOutput orchestrator bound to a setup worksheet and output linelist.
Signature:
Public Function Create(ByVal specSh As Worksheet, _
ByVal ll As Linelist) As AnalysisOutput
Factory method that creates a new AnalysisOutput instance tied to the given setup worksheet and output linelist. The setup worksheet holds 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 are created and populated. Both parameters are validated before construction.
Parameters:
specSh: Worksheet. The setup worksheet holding the analysis ListObjects (Tab_Global_Summary, Tab_Univariate_Analysis, Tab_Bivariate_Analysis, Tab_TimeSeries_Analysis, Tab_Spatial_Analysis, Tab_SpatioTemporal_Analysis).ll: Linelist. The output linelist workbook facade where analysis sheets will be created.
Returns: AnalysisOutput. A fully initialised orchestrator instance ready for use.
Throws:
- InvalidArgument When the specifications worksheet is Nothing.
- InvalidArgument When the linelist is Nothing.
Orchestration
WriteAnalysis #
write-analysis
Write all analysis tables, formulas and charts to the output.
Signature:
Public Sub WriteAnalysis(Optional ByVal part As Byte = AnalysisBuildStageAll)
Builds the four analysis sheets in order: normal (global summary, univariate and bivariate), time series, spatial and spatio-temporal. The stage says how far to go, and every sheet up to that point is finished, protected and hidden when it stayed empty.
The freeze-pane split of all four sheets runs at the end, in one pass. Activating a worksheet forces a repaint and a scroll sync that screen updating does not suppress, and it used to happen in the middle of every scope.
Parameters:
part: Optional Byte. A constant from the AnalysisBuildStage enum. Defaults to AnalysisBuildStageAll, which builds the four sheets. Any other value stops after the stage it names.
Remarks:
- This is what opens and restores the application state the build runs under: see the note at the top of this class. A raise inside the build restores it before the error travels on, so no failure leaves Excel with a frozen screen.
Throws:
- Whatever the build raises, after the application state is restored.
Checkings
TablesWritten #
tables-written
How many analysis tables this build put on a sheet
Signature:
Public Property Get TablesWritten() As Long
Returns: Long. The number of tables written.
GraphsWritten #
graphs-written
How many charts this build put on a sheet
Signature:
Public Property Get GraphsWritten() As Long
Returns: Long. The number of charts written.
HasCheckings #
has-checkings
Whether anything was reported during the build
Signature:
Public Property Get HasCheckings() As Boolean
Returns: Boolean. True when at least one entry was filed.
CheckingValues #
checking-values
The report of this build
Signature:
Public Property Get CheckingValues() As Checking
Returns: Checking. The store, or Nothing when nothing was filed.
Internal members (not exported)
Internal Properties
Seal #
seal
Seal the instance against further setup writes.
Signature:
Public Sub Seal()
Properties used during factory construction and internal wiring.
GuardNotSealed #
guard-not-sealed
Guard a setup setter against post-creation writes.
Signature:
Private Sub GuardNotSealed(ByVal propName As String)
Parameters:
propName: String. The property name for the error message.
OutputLL #
output-ll-get
Output linelist facade.
Signature:
Public Property Get OutputLL() As Linelist
Returns the Linelist reference representing the output workbook where analysis worksheets are created and populated.
Returns: Linelist. The output linelist workbook facade.
OutputLL #
output-ll-set
Assign the output linelist facade.
Signature:
Public Property Set OutputLL(ByVal ll As Linelist)
Parameters:
ll: Linelist. The output linelist workbook facade to store.
Wksh #
wksh-get
Setup worksheet reference.
Signature:
Public Property Get Wksh() As Worksheet
Returns the setup worksheet holding the analysis definition ListObjects.
Returns: Worksheet. The setup worksheet holding the analysis ListObjects.
Wksh #
wksh-set
Assign the setup worksheet reference.
Signature:
Public Property Set Wksh(ByVal specSh As Worksheet)
Parameters:
specSh: Worksheet. The setup worksheet to store.
Dependency Properties
LinelistData #
linelist-data
Linelist metadata facade.
Signature:
Private Property Get LinelistData() As LinelistSpecs
Convenience accessors for frequently used collaborators retrieved through the output linelist and its metadata facade.
Convenience accessor that retrieves the LinelistSpecs object from the stored output linelist. LinelistSpecs is the central metadata facade providing access to the dictionary, translation objects, formula data, design format, passwords and sheet configuration.
Returns: LinelistSpecs. Metadata facade for the output linelist.
DesignFormat #
design-format
Design format object.
Signature:
Private Property Get DesignFormat() As LLFormat
Convenience accessor for the LLFormat design format object used to apply visual formatting (fonts, colours, borders, cell styles) to analysis worksheets, cells and chart elements. Delegates through LinelistData to the shared format singleton so all analysis output uses consistent styling from the setup workbook.
Returns: LLFormat. Design format object for the output linelist.
TransObject #
trans-object
Translation object for a given scope.
Signature:
Public Property Get TransObject(Optional ByVal scope As Byte = TranslationOfMessages) As TranslationObject
Retrieves a TranslationObject for the requested translation scope. Translation objects resolve human-readable labels, button captions, sheet names and other locale-dependent strings from the setup workbook.
Parameters:
scope: Optional Byte. A constant from the TranslationScope enum. Defaults to TranslationOfMessages. Use TranslationOfShapes for button labels.
Returns: TranslationObject. Bound to the requested translation scope.
OutputSh #
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 held in the messages translation table (for example "LLSHEET_Analysis" for the normal scope), so the output sheet names match the configured language.
Each sheet is resolved once and kept. Resolving one costs a translated value and a worksheet lookup, and this property is read from the sheet preparation, the button placement, the freeze panes, every table and both chart passes.
Parameters:
scope: Optional Byte. A constant from the AnalysisScope enum saying which analysis worksheet to answer. Defaults to AnalysisScopeNormal.
Returns: Worksheet. The output analysis sheet in the linelist workbook.
Throws:
- ProjectError.InvalidArgument When the scope is outside the four.
OutputNames #
output-names
Metadata reader for the output worksheet of a scope.
Signature:
Private Property Get OutputNames(ByVal scope As Byte) As HiddenNames
One HiddenNames per output sheet, resolved once. Each Create walks the worksheet names and reads a comment on every tracked one, and this class used to build about ten of them per run.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Returns: HiddenNames. Reader bound to that scope's output sheet.
NamesObject #
names-object
Lazily-initialised analysis tracking object.
Signature:
Private Property Get NamesObject() As AnaTabIds
Lazily-initialised accessor for the AnaTabIds tracking object. AnaTabIds keeps the registry of chart metadata created during the analysis build, and the export reads it back to rebuild the charts in the exported workbook. The object is created once on first access, over the temporary analysis worksheet of the linelist.
Returns: AnaTabIds. Tracking object that records the chart metadata.
Remarks:
- The backing worksheet comes from lData.TemporarySheetName(TempSheetAnalysis), which must exist in the output linelist before this property is first read.
Scope Mapping
IsKnownScope #
is-known-scope
Whether a value is one of the four analysis scopes
Signature:
Private Function IsKnownScope(ByVal scope As Byte) As Boolean
The analysis scope, the chart scope, the sheet tag and the navigation prefix are four names for one thing. Each translation is stated here once, so no call site has to assume that two enums line up by number.
Parameters:
scope: Byte. The value to test.
Returns: Boolean. True for the four scopes.
GraphScopeOf #
graph-scope-of
The chart scope that goes with an analysis scope
Signature:
Private Function GraphScopeOf(ByVal scope As Byte) As Byte
GraphScope has three members and AnalysisScope has four. The two agree by number on the first three, and this class used to pass an analysis scope straight into a chart scope parameter. Spatio-temporal has no chart scope of its own, and its charts are laid out like the time series ones.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Returns: Byte. A constant from the GraphScope enum.
SheetTagOf #
sheet-tag-of
The sheet_type value that goes with an analysis scope
Signature:
Private Function SheetTagOf(ByVal scope As Byte) As String
EventLinelist, LLExporter, LLImporter and the epidemiological week helper all branch on this string, so an unknown scope raises here instead of stamping an empty tag.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Returns: String. The sheet_type value.
Throws:
- ProjectError.InvalidArgument When the scope is outside the four.
GoToPrefixOf #
goto-prefix-of
The navigation prefix that goes with an analysis scope
Signature:
Private Function GoToPrefixOf(ByVal scope As Byte) As String
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Returns: String. The prefix every navigation name of that sheet carries.
Application Helpers
AppScope #
app-scope
The application state this class builds under.
Signature:
Private Property Get AppScope() As ApplicationState
Built on first read and kept for the life of the instance. The snapshot is taken when the object is built, which is inside whatever state the caller was already in, so restoring hands that state back rather than guessing at one.
Returns: ApplicationState. Bound to the running Excel Application.
Remarks:
- WriteAnalysis is what opens and restores it: see the note at the top of this class.
SplitOutputSheet #
split-output-sheet
Apply the freeze-pane split to an analysis output worksheet.
Signature:
Private Sub SplitOutputSheet(ByVal scope As Byte)
Freezes the header rows and the left navigation columns so they stay visible while the user scrolls through the tables. The row split is 2 for the normal and spatial scopes and 3 for the time series and spatio-temporal ones, which carry an extra row for the header dropdown. The column split is always 3 and the zoom is 80%.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Remarks:
- Activating the sheet is what the freeze-pane API needs. A protected sheet or a hidden window makes it fail, and the failure is filed as a warning rather than passed over in silence.
- The busy state is written again after the activation, because activating a worksheet turns screen updating back on in some Excel versions. The scope is already busy at that point, which is why the call forces.
Sheet Preparation
AddCommands #
add-commands
Add the filter/update command button to an analysis output worksheet.
Signature:
Private Sub AddCommands(ByVal scope As Byte)
Places the command button that runs either the standard filter-update macro or the spatial one, depending on the scope. The button sits at row 2 column 2, is styled with the design format and is labelled with the translated SHP_Filter shape name. Exits early when the linelist is built from a template, because the template already carries the buttons.
This runs once per scope, from PrepareSheet, after the sheet format has been applied. It used to run a second time at the end of each scope; Buttons.Add short-circuits on an existing shape, so the second call stacked nothing and cost a Buttons instance, a shape scan, a translation and a format per scope. What the second call did lose was its own diagnostics, because the instance was created inside it and dropped.
Parameters:
scope: Byte. A constant from the AnalysisScope enum. The spatial scope gets the spatial update command.
StampSheetType #
stamp-sheet-type
Write the sheet_type tag of an analysis output worksheet
Signature:
Private Sub StampSheetType(ByVal scope As Byte)
The tag is what every runtime reader of the linelist uses to tell one analysis sheet from another, so a sheet that ends up empty gets it too.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
PrepareSheet #
prepare-sheet
Initialise an analysis output worksheet before any table is written.
Signature:
Private Sub PrepareSheet(ByVal scope As Byte)
Four steps: apply the AllAnalysisSheet base format to the whole worksheet, stamp the sheet_type tag, place the ComputedOnFiltered() warning formula at row 2 column 5 with the warning format, and add the command button.
The freeze-pane split is not part of this. Activating a worksheet forces a repaint that screen updating does not suppress, so the four splits are applied in one pass at the end of the build.
Parameters:
scope: Byte. A constant from the AnalysisScope enum. Decides the sheet_type tag and which update command the button carries.
GoTo Dropdown Helpers
AddGoTo #
add-goto
Create a data-validation dropdown for section, header or 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 one cell that navigates to a named section, header or graph on the analysis sheet. Selecting an entry runs the GoTo macro that scrolls to the matching named range. The cell is formatted as a selection dropdown, its initial value is the label, and it is given a workbook-level name.
An empty list leaves the cell without a dropdown and still names it. EventLinelist reads those names without guarding, and the one entry that used to keep the normal sheet's list non-empty was a dropdown entry that navigated nowhere.
Parameters:
cellRng: Range. The single cell the dropdown goes in.dropArray: BetterArray. Display strings for the entries.goToLabel: String. The default display value written into the cell.goToPrefix: Optional String. Short prefix for the name, one per analysis sheet. Defaults to "ua_".goToSuffix: Optional String. Suffix telling a section-level dropdown from a graph-level one. Defaults to vbNullString.
Temporal Section Helpers
WriteSectionBounds #
write-section-bounds
Write the two date bounds of a temporal section
Signature:
Private Sub WriteSectionBounds(ByVal outsh As Worksheet, ByVal secId As String, _
ByVal minFormula As String, ByVal maxFormula As String)
Writing out a temporal section once the loop has finished with it.
MIN_MIN_DATE_
Parameters:
outsh: Worksheet. The analysis sheet the names live on.secId: String. Identifier of the section.minFormula: String. The complete formula for the earliest date.maxFormula: String. The complete formula for the latest date.
NameSpatioTemporalColumn #
name-spatio-temporal-column
Name the formula column that spans a spatio-temporal section
Signature:
Private Sub NameSpatioTemporalColumn(ByVal outsh As Worksheet, ByVal secId As String, _
ByVal lastTabId As String)
GeoModule reads SPT_FORMULA_COLUMN_
Parameters:
outsh: Worksheet. The analysis sheet.secId: String. Identifier of the section.lastTabId: String. Identifier of the last table of the section.
CloseTemporalSection #
close-temporal-section
Finish a temporal section and write everything it held
Signature:
Private Sub CloseTemporalSection(ByVal outsh As Worksheet, _
ByVal section As TemporalSection, _
ByVal scope As Byte, _
ByVal goToHeaderLabel As String)
Writes the two date bounds, adds the header dropdown two rows under the section anchor, and names the spatio-temporal formula column. Does nothing when no section is open, so the caller can call it at every section boundary and once more after the loop.
Parameters:
outsh: Worksheet. The analysis sheet.section: TemporalSection. The section holder.scope: Byte. A constant from the AnalysisScope enum.goToHeaderLabel: String. Translated label of the header dropdown.
AddSectionGoTo #
add-section-go-to
Hang the header dropdown of one section under its anchor
Signature:
Private Sub AddSectionGoTo(ByVal outsh As Worksheet, ByVal secId As String, _
ByVal headers As BetterArray, ByVal scope As Byte, _
ByVal goToHeaderLabel As String)
The anchor is SECTION_
Parameters:
outsh: Worksheet. The analysis sheet.secId: String. Identifier of the section.headers: BetterArray. The entries of the dropdown.scope: Byte. A constant from the AnalysisScope enum.goToHeaderLabel: String. Translated label of the dropdown.
NameGraphStart #
name-graph-start
Name the cell the charts of a temporal sheet start at
Signature:
Private Sub NameGraphStart(ByVal outsh As Worksheet, ByVal secId As String, _
ByVal scope As Byte)
The charts go five rows under the last table of the sheet. Both chart passes read this name, and it is created once the tables are done.
Parameters:
outsh: Worksheet. The analysis sheet.secId: String. Identifier of the last section of the sheet.scope: Byte. A constant from the AnalysisScope enum.
Table Creation
WriteTable #
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 scope As Byte)
Core table-creation loop and supporting write logic.
Core table-creation loop. Walks every data row of the setup ListObject named by loName and, for each valid row, creates a TableSpecs, builds a CrossTable on the output sheet, applies the formulas, formats the table and, for a row that asks for one, creates a chart. For the time series and spatio-temporal scopes it also carries the open TemporalSection: a row that starts a new section closes the one before it, and the last section is closed after the loop.
Each row runs inside a per-table error handler, so one malformed row is skipped and named in the generation report while the rest of the scope is built.
Parameters:
loName: String. Name of the setup ListObject whose rows define the tables.sectionsList: BetterArray. Collects the section entries of the sheet-level navigation dropdown. Passed ByVal and grown through Push.scope: Byte. A constant from the AnalysisScope enum. Decides which output sheet receives the tables.
Remarks:
- Exits early when the ListObject has no data row.
ChartAnchorOf #
chart-anchor-of
The cell a table's chart hangs from.
Signature:
Private Function ChartAnchorOf(ByVal tabl As CrossTable, _
ByVal outsh As Worksheet) As Range
Two rows above the table and two columns past its last one, which is where the chart used to be placed inline. A spatial table carries two more columns of controls, so its chart starts further right. The table's own geometry is read from the instance, which holds it once Build has run, so this answers the same cell whether it is asked during the table pass or after it.
Parameters:
tabl: CrossTable. The built table.outsh: Worksheet. The output worksheet.
Returns: Range. The anchor cell.
ReserveChartRows #
reserve-chart-rows
Hold the rows a deferred chart will cover.
Signature:
Private Sub ReserveChartRows(ByVal tabl As CrossTable, ByVal outsh As Worksheet, _
ByVal scope As Byte)
The next table is placed below the charts of the tables above it, and those charts are no longer there to be measured when the placing happens. Graphs answers how tall the chart will be in rows of this sheet, and the table keeps the line.
Parameters:
tabl: CrossTable. The table whose chart is owed.outsh: Worksheet. The output worksheet.scope: Byte. A constant from the AnalysisScope enum.
DrawPendingCharts #
draw-pending-charts
Draw every chart the table pass put off, in one pass.
Signature:
Private Sub DrawPendingCharts(ByVal pending As Collection, ByVal outsh As Worksheet, _
ByVal namObj As AnaTabIds, ByVal scope As Byte)
The charts used to be drawn one per table, in the middle of writing the tables. Excel 16.112 dies on the FIRST of them: the table before it is complete, the chart takes both its series, and the host falls over on the next call. Drawing them together keeps every chart operation out of the table writing, which is the thing being tested.
A table carries everything a chart needs -- its own geometry and its specification -- so the pass holds cross-tables and reads the rest back here.
Each chart is guarded on its own. The inline block sat inside the per-table handler, so a chart that failed cost its table and nothing more; the same has to be true here, or one bad chart would cost every chart after it.
Parameters:
pending: Collection. The CrossTable instances owed a chart, in table order.outsh: Worksheet. The output worksheet.namObj: AnaTabIds. The registry the export reads back.scope: Byte. A constant from the AnalysisScope enum.
Graph Creation
AddGraphSeries #
add-graph-series
Add one series to a chart and register it for the export
Signature:
Private Sub AddGraphSeries(ByVal gr As Graphs, ByVal namObj As AnaTabIds, _
ByVal scope As Byte, ByVal graphId As String, _
ByVal seriesName As String, ByVal seriesType As String, _
ByVal seriesPos As String, ByVal seriesLabel As String, _
ByVal seriesColumnLabel As String, _
ByVal hardCodeLabels As Boolean, _
ByVal outRangeAddress As String, _
Optional ByVal prefix As String = vbNullString, _
Optional ByVal prefixOnly As Boolean = False)
The two chart passes that run after the tables of a sheet are written, and the two steps they share.
The chart and the registry have to be told the same thing about a series, and three places told them separately. AnaTabIds.AddGraphInfo takes nine required arguments; one of those three left the ninth out, which is a compile fault in an early-bound call, so the whole file stopped compiling. One call site cannot make that mistake twice.
Parameters:
gr: Graphs. The chart being built.namObj: AnaTabIds. The registry the export reads back.scope: Byte. A constant from the AnalysisScope enum.graphId: String. Identifier of the chart.seriesName: String. Named range holding the series data.seriesType: String. Chart type of the series.seriesPos: String. Axis the series is plotted against.seriesLabel: String. Named range holding the category labels.seriesColumnLabel: String. Named range holding the column header labels.hardCodeLabels: Boolean. True writes the labels as literals.outRangeAddress: String. Address the chart is placed at.prefix: Optional String. Label prefix. Defaults to vbNullString.prefixOnly: Optional Boolean. True uses the prefix as the whole label.
FinishGraph #
finish-graph
Format a chart, register its look and harvest what it reported
Signature:
Private Sub FinishGraph(ByVal gr As Graphs, ByVal namObj As AnaTabIds, _
ByVal scope As Byte, ByVal graphId As String, _
ByVal catTitle As String, ByVal valuesTitle As String, _
ByVal hardCodeLabels As Boolean, _
ByVal heightFactor As Long, ByVal plotTitle As String)
The second half every chart shares. The chart scope comes from the analysis scope through GraphScopeOf, so a chart is never formatted against a number that happens to line up.
Parameters:
gr: Graphs. The chart being finished.namObj: AnaTabIds. The registry the export reads back.scope: Byte. A constant from the AnalysisScope enum.graphId: String. Identifier of the chart.catTitle: String. Category axis title.valuesTitle: String. Value axis title.hardCodeLabels: Boolean. True writes the labels as literals.heightFactor: Long. Height multiplier of the chart.plotTitle: String. Chart title.
GraphAnchor #
graph-anchor
The cell the charts of a sheet start at
Signature:
Private Function GraphAnchor(ByVal outsh As Worksheet, ByVal anchorName As String) As Range
The name is created after the last table of the sheet is written, so a scope whose tables all failed does not carry it. Answering Nothing is what lets the caller give up on the charts rather than end the whole build.
Parameters:
outsh: Worksheet. The analysis sheet.anchorName: String. Name of the anchor cell.
Returns: Range. The anchor cell, or Nothing when the name is absent.
WriteTimeSeriesGraphs #
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)
Reads three setup ListObjects: the graph definition table, the graph title table and the time series table. TimeSeriesGraphs resolves them into multi-series graphs with mixed chart types and separate axis positions. Each graph is then created, its series added and registered, formatted and given its title cell, and the anchor moves down fifty rows. A graph dropdown is placed at row 3 column 3 at the end.
Parameters:
graphLoName: String. Name of the ListObject defining the graph series.graphTitleLoName: String. Name of the ListObject defining the titles.tabLoName: String. Name of the time series table ListObject.graphsList: BetterArray. Collects the graph entries of the dropdown.
Remarks:
- Exits early when the sheet holds no table, when either definition ListObject has no data row, or when the charts have no anchor to start from.
WriteSpatioTemporalGraph #
write-spatio-temporal-graph
Build the spatio-temporal charts from the table definition ListObject.
Signature:
Private Sub WriteSpatioTemporalGraph(ByVal loName As String, _
ByVal graphsList As BetterArray)
Walks the same setup ListObject the spatio-temporal tables were built from and creates one chart per row that asks for one. The plot title is the translated graph label and the value of the table's start column. Charts are spaced fifty rows apart, and a graph dropdown is placed at row 3 column 3 at the end.
Parameters:
loName: String. Name of the spatio-temporal ListObject.graphsList: BetterArray. Collects the graph entries of the dropdown.
Remarks:
- Skips a row that is not a valid table or asks for no chart. Exits early when the ListObject has no data row or the charts have no anchor.
Orchestration
ScopeHasRows #
scope-has-rows
Whether any setup ListObject of a scope carries a row
Signature:
Private Function ScopeHasRows(ByVal loNames As BetterArray) As Boolean
Top-level entry point that builds the four analysis output worksheets.
Formatting an analysis sheet writes a font size and a column width over all sixteen thousand columns, and a scope with no row is hidden at the end of its own build anyway.
Parameters:
loNames: BetterArray. Names of the setup ListObjects of the scope.
Returns: Boolean. True when at least one of them has a data row.
BuildScope #
build-scope
Build one analysis sheet from end to end
Signature:
Private Sub BuildScope(ByVal scope As Byte, ByVal loNames As BetterArray, _
ByVal buildGraphs As Boolean)
The four scopes were four copies of the same twenty lines. Each one prepares its sheet, writes its tables, adds its charts, hangs the section dropdown at row 2 column 3, protects the sheet and hides it when nothing was written.
Parameters:
scope: Byte. A constant from the AnalysisScope enum.loNames: BetterArray. Names of the setup ListObjects to walk, in order.buildGraphs: Boolean. True runs the chart pass of the scope.
ScopeTables #
scope-tables
The setup ListObjects one scope is built from
Signature:
Private Function ScopeTables(ByVal scope As Byte) As BetterArray
Parameters:
scope: Byte. A constant from the AnalysisScope enum.
Returns: BetterArray. The ListObject names, in the order they are written.
Checkings
LogInfo #
log-info
Record one entry in this class's own checking store
Signature:
Private Sub LogInfo(ByVal label As String, Optional ByVal scope As Byte = checkingSuccess)
The key names this class. Every collaborator of a build files its entries into one report, Checking.Add raises on a duplicate key, and a bare counter starting at zero is what each of them used to write.
Parameters:
label: String. The message to record.scope: Optional Byte. Severity from CheckingLogType. Defaults to checkingSuccess.
HarvestCollaboratorCheckings #
harvest-collaborator-checkings
Fold a collaborator's entries into the report of this build
Signature:
Private Sub HarvestCollaboratorCheckings(ByVal collaboratorChecks As Checking)
Parameters:
collaboratorChecks: Checking. The collaborator's store.
LogMilestone #
log-milestone
File one entry for a table or a chart put on a sheet
Signature:
Private Sub LogMilestone(ByVal label As String)
A linelist carries tens of analysis tables and charts, so these entries go to the __check worksheet with the problems. They are what shows the analysis phase did work, where a clean phase used to look the same whether it built forty tables or none.
Parameters:
label: String. The message for the report.
Error Handling
ThrowError #
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:
errNumber: Long. The error code to raise.message: String. Human-readable description of the failure.
Throws:
- ProjectError.
Always raises the specified error.
Used in (22 file(s))
- Analysis.cls
- AnaTabIds.cls
- CrossTable.cls
- CrossTableFormula.cls
- SpatialTables.cls
- LLSpatial.cls
- Graphs.cls
- GraphSeries.cls
- TimeSeriesGraphs.cls
- LLTranslation.cls
- EventsDesignerAdvanced.bas
- HeadlessBuild.bas
- LinelistEventsManager.bas
- TestAnalysisOutput.bas
- TestAnaTabIds.bas
- TestCrossTable.bas
- TestCrossTableFormula.bas
- TestFormulaBuilder.bas
- TestTemporalSection.bas
- TestApplicationState.bas
- TestGraphs.bas
- TestGraphSeries.bas