GraphSeries
The chart series of one built cross-table: univariate, bivariate, spatial or spatio-temporal. It reads the table scope and the graph settings off TableSpecs and answers one SeriesBuffer. AnalysisOutput walks that buffer and hands each entry to Graphs.
THE SERIES ARE BUILT ON THE FIRST READ
Series() builds the buffer the first time it is asked and holds the answer. The reasons a series was left out are filed while the buffer is being built, so HasCheckings is read after Series().
EVERY SKIP IS REPORTED
This class builds fewer series than the setup asked for in four cases: a scope it has no builder for, a graph setting it does not recognise, a percentage chart on a table with no percentage column, and a table that ends with no series at all. Each one files an entry through LogInfo, and AnalysisOutput reads them into the generation report.
Depends on: CrossTable, TableSpecs, SeriesBuffer, Checking
Version: 1.0 (2026-07-31)
Instantiation
Create #
create
Create the series builder of one cross-table
Signature:
Public Function Create(ByVal tabl As CrossTable) As GraphSeries
Time series tables are drawn by TimeSeriesGraphs, which reads the three graph setup tables. Global summary tables carry no chart at all.
Parameters:
tabl: CrossTable. The cross-table whose named ranges hold the data to plot. The named ranges have to be on the worksheet before the buffer is read.
Returns: GraphSeries. A builder ready for Series().
Throws:
- ProjectError.InvalidArgument When tabl is Nothing, a time series table or a global summary table.
Reading
Series #
series
The series of this table
Signature:
Public Property Get Series() As SeriesBuffer
Builds on the first read and keeps the answer. A buffer whose Count is 0 says the table asks for a chart that carries nothing, and the reason is in the report.
Returns: SeriesBuffer. One entry per series, in plot order.
Wksh #
wksh
The worksheet the named ranges of this table live on
Signature:
Public Property Get Wksh() As Worksheet
Returns: Worksheet. The worksheet of the cross-table.
Checking
HasCheckings #
has-checkings
Whether anything was reported while the series were built
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)
Instantiation
Seal #
seal
Seal the instance against further setup writes
Signature:
Public Sub Seal()
Called by the factory after the last setup write. Once sealed, the creation-only setters raise through ThrowError.
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 reported in the error message.
Table #
table
The cross-table this builder reads
Signature:
Public Property Get Table() As CrossTable
Returns: CrossTable. The stored cross-table.
Table #
table-set
Assign the cross-table
Signature:
Public Property Set Table(ByVal tabl As CrossTable)
Parameters:
tabl: CrossTable. The cross-table to store.
Building
BuildSeries #
build-series
Build the buffer from the table scope and its graph settings
Signature:
Private Sub BuildSeries()
FlipCoordinates controls the plot direction: horizontal bars when it answers True, vertical bars otherwise. For a spatio-temporal table the column count is the geographic unit count and the row categories are the ones of the section, because every table of a section shares them.
Remarks:
- TableSpecs.GeoCount carries the default of 5 and clamps the value to 1 to 20, so an empty or unreadable cell needs no guard here.
BuildUnivariateSeries #
build-univariate-series
Build the series of a single-variable table
Signature:
Private Sub BuildUnivariateSeries(ByVal tabId As String, _
ByVal plotType As String, _
ByVal hasPerc As Boolean)
One bar series over the value column, labelled by the row categories and named by the column label. A table carrying percentages gets a second series of points on the right axis, so the percentages sit over the bars. Horizontal bars are left without that overlay, because a point series on a horizontal chart reads poorly.
Parameters:
tabId: String. The table identifier every named range carries.plotType: String. "bar" for vertical bars, "hbar" for horizontal ones.hasPerc: Boolean. Whether the table carries a percentage column.
BuildMultiColumnSeries #
build-multi-column-series
Build the series of a table with several data columns
Signature:
Private Sub BuildMultiColumnSeries(ByVal specs As TableSpecs, _
ByVal tabId As String, _
ByVal tabSecId As String, _
ByVal tabType As Byte, _
ByVal nbCols As Long, _
ByVal plotType As String)
The graph mode comes from TableSpecs.GraphMode. "values" and "yes" give one bar series per column over the value ranges. "percentages" gives one bar series per column over the percentage ranges, and reports when the table carries none. "both" gives value bars on the left axis and percentage points on the right, per column. A spatio-temporal table takes its row categories from its section.
Parameters:
specs: TableSpecs. The specifications of the table.tabId: String. The table identifier every named range carries.tabSecId: String. The section identifier, for a spatio-temporal table.tabType: Byte. The table scope.nbCols: Long. How many data columns to walk.plotType: String. "bar" or "hbar".
Remarks:
- A graph mode outside the three the setup dropdowns offer files an error entry. It used to fall through the Select Case with no arm, which left the chart with no series and raised 1004 in Graphs.Format two frames later.
Checking
SpecsId #
specs-id
A name for this instance that no other instance shares
Signature:
Private Function SpecsId() As String
The report of everything this builder decided to leave out.
AnalysisOutput merges the entries of every collaborator into one report, and Checking.Add raises on a duplicate key, so a key made of a bare counter collides as soon as two instances file an entry. One instance serves one table, so the table identifier names it.
Returns: String. The identifier every key of this instance carries.
LogInfo #
log-info
Record a diagnostic entry in the internal checking store
Signature:
Private Sub LogInfo(ByVal label As String, _
Optional ByVal scope As Byte = checkingNote)
Creates the Checking store on first use and appends the message under a key naming this class, this table and a counter.
Parameters:
label: String. The message to record.scope: Optional Byte. Severity from CheckingLogType. Defaults to checkingNote.
ErrorHandling
ThrowError #
throw-error
Raise a ProjectError-based exception
Signature:
Private Sub ThrowError(ByVal errNumber As Long, ByVal message As String)
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 (4 file(s))
- AnalysisOutput.cls
- TableSpecs.cls
- Graphs.cls
- TestGraphSeries.bas