LLDataEntry

Builds one data entry worksheet of a generated linelist from the dictionary. Consumers call Create with a layer mode, a sheet name and the linelist facade, then call Build. Entries filed along the way leave through HasCheckings and CheckingValues.

WHAT EACH LAYER GETS

An HList sheet gets the design format, frozen panes, five action buttons, its sections, the GoTo dropdown, the sheet metadata, a ListObject, a printed companion sheet, a filtered companion sheet, a pivot table and protection.

A VList sheet gets the design format, a freeze on row 1, its sections, the GoTo dropdown, the sheet metadata, a PLAGEVALUES named range and protection. The ListObject, the two companion sheets, the pivot table and the action buttons belong to the HList layer alone.

WHAT A FAILURE LEAVES BEHIND

Both builders protect their worksheet whichever way they leave, file the failure for the generation report and raise it again. The caller offers the user the incomplete workbook to inspect, so a sheet that failed part way through is reachable and it is protected when the user gets there.

Screen updating belongs to the caller. EventsDesignerAdvanced.clickGenerate turns it off through ApplicationState for the whole generation and restores it on both its exits.

PUBLISHED STATE

The worksheet-level hidden names this class writes, and who reads each: sheet_type EventLinelist, LLExporter, LLImporter, LLGeo, LLSpatial, ExportButton, CustomLinelistFunctions table_name EventLinelist, LLImporter, LLGeo, LLSpatial, EventsLinelistButtons blank_row_count LLImporter.HasData, EventsLinelistButtons. It holds the number of filled cells an untouched data row carries, which is the threshold CustomTable.RemoveRows compares against. filtered_sheet EventLinelist, LLExporter, LLSpatial, ExportButton

_go_to_section the GoTo dropdown validation

Depends on: Linelist, LLSheets, LinelistSpecs, LLdictionary, LLFormat, DropdownLists, Passwords, TranslationObject, Buttons, CustomPivotTable, HiddenNames, SectionBuilder, Checking, BetterArray, The prefix Linelist.ScopedName puts on a CRF companion. Spelled the same way, there and in EventsLinelistButtons, and it is part of the sheet's stored table, name, so it is copied here exactly., What Excel accepts for a worksheet name. Linelist.ScopedName cuts to the same, figure, so a longer name still builds; this class reads it to tell the user, which dictionary names come out shortened., How far the printed companion is grown once its ListObject is made, and the, same headroom the filtered companion is given., Button shape codes

Version: 1.1 (2026-07-31)

Instantiation

Create #

create

Create a LLDataEntry instance

Signature:

Public Function Create(ByVal layer As Byte, _
                       ByVal sheetName As String, _
                       ByVal ll As Linelist, _
                       Optional ByVal sheetInfo As LLSheets) As LLDataEntry

Factory method and Friend bindings for construction.

Creates a new LLDataEntry wired to build a data entry sheet of the given layer type (HList or VList) for the named sheet within the linelist. The linelist object, the layer, the sheet name and its presence in the dictionary are all validated before construction.

The caller may hand in the LLSheets instance it already holds. LLSheets caches the resolved dictionary row and the variable count per instance, so one instance shared across a whole build searches the dictionary once per sheet. Five instances searched it five times.

Parameters:

  • layer: Byte. The LLDataEntryLayer mode (HList = 1, VList = 2).
  • sheetName: String. The dictionary sheet name to build.
  • ll: Linelist. The linelist workbook facade providing worksheets, dropdowns, pivots, and specs.
  • sheetInfo: Optional LLSheets. Sheet metadata over the same dictionary. A new one is built when the caller has none.

Returns: LLDataEntry. A fully initialised instance ready for Build.

Throws:

  • ProjectError.ObjectNotInitialized When ll is Nothing.
  • ProjectError.InvalidArgument When sheetName is empty, when the layer is unknown, or when the sheet is absent from the dictionary.

Seal #

seal

Close the instance to creation-only writes

Signature:

Public Sub Seal()

Called by the factory once the four bindings are in place. Swapping the layer or the sheet name part way through a build would write one sheet's metadata onto another, so the setters refuse a second write.


Core

Build #

build

Build the data entry sheet

Signature:

Public Sub Build()

Public entry point for building the data entry sheet.

Dispatches to the private builder of the layer set during factory construction. HList mode delegates to BuildHList; VList mode delegates to BuildVList.

Throws:

  • ProjectError.InvalidArgument When the layer value is not LLDataEntryLayerHList or LLDataEntryLayerVList.

Checkings

HasMilestones #

has-milestones

Whether any variable of this sheet was written

Signature:

Public Property Get HasMilestones() As Boolean

Returns: Boolean. True once a variable of this sheet reached the worksheet.


MilestoneValues #

milestone-values

The per-variable record of this sheet

Signature:

Public Property Get MilestoneValues() As Checking

Handed up from the section builder as the writer holds it. The build driver takes it into the run log record-only, so it reaches the text file and leaves the __check worksheet to the sheet-level entries and the problems.

Returns: Checking. The milestone entries, or Nothing.


VariablesWritten #

variables-written

How many variables this sheet build put on the worksheet

Signature:

Public Property Get VariablesWritten() As Long

Returns: Long. The number of variables written.


SectionsPlaced #

sections-placed

How many sections this sheet build laid out

Signature:

Public Property Get SectionsPlaced() As Long

Returns: Long. The number of sections placed.


HasCheckings #

has-checkings

Whether this build has anything to report

Signature:

Public Property Get HasCheckings() As Boolean

Answers True once an entry has been filed. The caller tests this before reading CheckingValues and pushes the result into the generation report.

Returns: Boolean. True when there is something to read.


CheckingValues #

checking-values

The report entries of this sheet build

Signature:

Public Property Get CheckingValues() As Checking

Answers the Checking object holding the entries, and Nothing while none have been filed. EventsDesignerAdvanced flushes it as phase 2 of the generation report, once every data entry sheet is built.

Returns: Checking. The entries, or Nothing.


Internal members (not exported)

Bindings

BinLayer #

bin-layer

Assign the builder layer mode

Signature:

Friend Property Let BinLayer(ByVal value As Byte)

Friend setters used only during factory construction.

Parameters:

  • value: Byte. The LLDataEntryLayer constant (HList or VList).

Throws:

  • ProjectError.SomethingWentWrong When the instance is already sealed.

BinSheetName #

bin-sheet-name

Assign the target sheet name

Signature:

Friend Property Let BinSheetName(ByVal value As String)

Parameters:

  • value: String. The dictionary sheet name to build.

Throws:

  • ProjectError.SomethingWentWrong When the instance is already sealed.

BinLinelist #

bin-linelist

Assign the linelist facade

Signature:

Friend Property Set BinLinelist(ByVal value As Linelist)

Parameters:

  • value: Linelist. The linelist workbook facade.

Throws:

  • ProjectError.SomethingWentWrong When the instance is already sealed.

BinSheetInfo #

bin-sheet-info

Assign the sheet metadata reader

Signature:

Friend Property Set BinSheetInfo(ByVal value As LLSheets)

Parameters:

  • value: LLSheets. Sheet metadata over the linelist dictionary.

Throws:

  • ProjectError.SomethingWentWrong When the instance is already sealed.

ReportSheetNameLength #

report-sheet-name-length

File a report entry for a sheet name whose companions come out shortened

Signature:

Friend Sub ReportSheetNameLength()

Excel accepts 31 characters and Linelist.ScopedName cuts every worksheet name to that, on creation and on lookup alike, so a long name still builds. What the user loses is the choice of what the shortened companion is called, and this says so at validation time, before any sheet is made.

The printed companion carries the longest prefix, so an HList sheet name has six characters less room than a VList one.


HListBuild

BuildHList #

build-hlist

Build a horizontal data entry sheet

Signature:

Private Sub BuildHList()

Private implementation for horizontal data entry sheet construction.

Constructs a full HList sheet: applies design formatting, freezes panes, adds action buttons (Show/Hide, Add Rows, Clear Filters, Open Print, and optionally Geo), builds sections via SectionBuilder, creates the GoTo section dropdown, stores sheet metadata as hidden names, creates the main ListObject table plus printed and filtered companion sheets, adds a pivot table, and protects the sheet. When a template workbook is in use, buttons are skipped and rows 3-4 are hidden instead.

A failure anywhere in that run reaches the handler at the foot of this routine, which protects the sheet, puts screen updating back, files the failure for the generation report and re-raises what it caught.


VListBuild

BuildVList #

build-vlist

Build a vertical data entry sheet

Signature:

Private Sub BuildVList()

Private implementation for vertical data entry sheet construction.

Constructs a VList sheet: applies design formatting, freezes pane row 1, builds sections via SectionBuilder, creates the GoTo section dropdown, stores sheet metadata as hidden names, computes the PLAGEVALUES range reference and protects the sheet.

A failure anywhere in that run reaches the handler at the foot of this routine, which protects the sheet, puts screen updating back, files the failure for the generation report and re-raises what it caught.


Helpers

ProtectCompanion #

protect-companion

Protect a print or CRF companion with every cell left editable

Signature:

Private Sub ProtectCompanion(ByVal companionSh As Worksheet, ByVal pass As Passwords)

Private utilities shared by both build modes.

The two companions hold no data of their own. The print sheet is a view of the table beside it and the CRF is a form to fill in on paper, so a user who wants to retype a header, widen a column or drop a row on one of them should never be stopped. Every cell is unlocked before the sheet is protected, which leaves nothing for Contents to guard.

The protect call is still made, and it is made for the UserInterfaceOnly flag it carries. That flag is what lets the show/hide bracket, the import walk and the export walk write to the companion, and it is also what puts a row for the companion into the protection matrix. The two flags the matrix records -- shapes and row deletion -- are both asked for as yes, so the row it writes says both are allowed and LeaveDebugMode restores the sheet the same way.

Parameters:

  • companionSh: Worksheet. The print or CRF sheet. Nothing is skipped.
  • pass: Passwords. The protection keys. Nothing is skipped.

FreezeHeader #

freeze-header

Freeze the header of a data entry sheet

Signature:

Private Sub FreezeHeader(ByVal sh As Worksheet, ByVal splitRow As Long, _
                         Optional ByVal splitColumn As Long = 0)

ActiveWindow belongs to whichever sheet is active, so the activation is tested before the three writes. A sheet that refuses to activate - a hidden one, or a workbook whose structure is protected - used to have the freeze applied to whatever worksheet was active at the time, with no message.

Parameters:

  • sh: Worksheet. The sheet whose panes are frozen.
  • splitRow: Long. The row the horizontal split sits under.
  • splitColumn: Optional Long. The column the vertical split sits after. Zero leaves the columns unsplit.

BuildSections #

build-sections

Build sections using SectionBuilder

Signature:

Private Sub BuildSections(ByVal sh As Worksheet, _
                          ByVal printSh As Worksheet, _
                          Optional ByVal crfSh As Worksheet = Nothing)

Creates a SectionBuilder in the appropriate mode (HList or VList) and invokes its Build method. Both standard and custom dropdown objects are passed to the builder for variable validation setup.

The CRF companion arrives as a parameter. It used to be looked up here under a suppressed error, which read as "use it when it happens to be there" and hid the fact that nothing ever created it.

Parameters:

  • sh: Worksheet. The main data entry sheet to build sections on.
  • printSh: Worksheet. The printed companion sheet (Nothing for VList).
  • crfSh: Worksheet. The CRF companion sheet (Nothing for VList).

BuildGoToSection #

build-goto-section

Write the GoTo section dropdown into cell A1

Signature:

Private Sub BuildGoToSection(ByVal sh As Worksheet, _
                             ByVal shHn As HiddenNames, _
                             ByVal tableName As String, _
                             ByVal design As LLFormat, _
                             ByVal drop As DropdownLists, _
                             ByVal messages As TranslationObject)

The same twenty lines used to sit in each builder, and the two copies of the dictionary index they carried drifted apart by one row. One copy is what keeps them together.

Parameters:

  • sh: Worksheet. The data entry sheet.
  • shHn: HiddenNames. The hidden name store of that sheet.
  • tableName: String. The sheet's table name from the dictionary.
  • design: LLFormat. The design format of the linelist.
  • drop: DropdownLists. The standard dropdown manager of the linelist.
  • messages: TranslationObject. The message translation scope.

WriteSheetMetadata #

write-sheet-metadata

Record the kind of sheet this is and the table it carries

Signature:

Private Sub WriteSheetMetadata(ByVal store As HiddenNames, _
                               ByVal sheetType As String, _
                               ByVal tableName As String)

Parameters:

  • store: HiddenNames. The hidden name store of the sheet.
  • sheetType: String. "HList", "HList Print" or "VList".
  • tableName: String. The name of the sheet's table.

NameValuesRange #

name-values-range

Name the block of value cells of a VList sheet

Signature:

Private Sub NameValuesRange(ByVal sh As Worksheet, ByVal tableName As String)

The walk starts one column left of the table marker, which is the column carrying the variable labels, and runs down until it meets an empty cell. The named range ends on that empty cell, so it holds one row past the last value: that row is where the next value lands, and EventLinelist recalculates the whole named range when a cell in it changes.

The walk is bounded by the last row of the worksheet. A marker sitting in column A is reported, because the column to its left is off the sheet.

Parameters:

  • sh: Worksheet. The VList data entry sheet.
  • tableName: String. The sheet's table name from the dictionary.

SectionStartRow #

section-start-row

The dictionary index of this sheet's first variable

Signature:

Private Function SectionStartRow() As Long

LLSheets.RowIndex answers an absolute worksheet row. The dictionary data range is taken without its header and the linelist dictionary keeps that header on worksheet row 1, so worksheet row R is index R - 1. Both readers of the dictionary in this class go through here, which is what holds them together: the two used to differ by one and a sheet whose first section held a single variable lost that section from its GoTo dropdown.

Returns: Long. The 1-based index into the dictionary data range.


CollectSectionNames #

collect-section-names

Collect section names for the GoTo dropdown

Signature:

Private Function CollectSectionNames(ByVal goToLabel As String) As BetterArray

Walks the dictionary rows of the current sheet and keeps each new section name in the order it appears, prefixed with the GoTo label. A section that repeats on consecutive rows is kept once.

The two columns are read into memory in one crossing each. Reading them a cell at a time cost two crossings per dictionary row, per sheet built.

Parameters:

  • goToLabel: String. The translated "Go to section" prefix label.

Returns: BetterArray. A 1-based array of prefixed section name strings.


ColumnOf #

column-of

Read one dictionary column into a 1-based array

Signature:

Private Function ColumnOf(ByVal dict As LLdictionary, ByVal columnName As String) As Variant

A one-cell range answers a scalar, and a column the dictionary does not carry answers Nothing. Both come back as a one-entry array holding an empty string, so the caller walks the same shape in every case.

Parameters:

  • dict: LLdictionary. The linelist dictionary.
  • columnName: String. The dictionary column to read.

Returns: Variant. A 1-based array of the column's values.


EnsureAndSet #

ensure-and-set

Give a hidden name its value, creating it when it is absent

Signature:

Private Sub EnsureAndSet(ByVal store As HiddenNames, ByVal nameId As String, _
                         ByVal value As Variant, _
                         Optional ByVal valueType As Byte = HiddenNameTypeString)

HiddenNames.EnsureName writes the value only when it creates the name, so a name that is already there keeps whatever it held. AddOutputSheet reuses a worksheet a template workbook already carries, and every one of these names is read by other classes, so a second build has to overwrite what the first one wrote.

Parameters:

  • store: HiddenNames. The hidden name store.
  • nameId: String. The hidden name identifier.
  • value: Variant. The value to write.
  • valueType: Optional Byte. The stored type. Defaults to a string.

Checkings

LogInfo #

log-info

File one entry against the sheet being built

Signature:

Private Sub LogInfo(ByVal label As String, Optional ByVal scope As Byte = checkingSuccess)

The key carries the sheet name, so the entries of two sheets can be merged into one Checking. The counter alone started at 0 in every instance and Checking.Add raises on a duplicate, so the second sheet of a run stopped the caller. SectionBuilder keys its entries by worksheet and variable for the same reason.

Parameters:

  • label: String. The message for the report.
  • scope: Optional Byte. Severity. Defaults to checkingSuccess.

HarvestCollaboratorCheckings #

harvest-collaborator-checkings

Fold what a collaborator filed into this sheet's entries

Signature:

Private Sub HarvestCollaboratorCheckings(ByVal collaboratorChecks As Checking)

The two shared dropdown managers are left out on purpose. Linelist keeps one instance of each for the whole build and the generation report flushes them once, after every sheet is built, so folding them in here would report each of their warnings once per data entry sheet as well.

Parameters:

  • collaboratorChecks: Checking. What the collaborator filed.

BuiltCountsText #

built-counts-text

The section and variable counts of the finished sheet

Signature:

Private Function BuiltCountsText() As String

Read off the section builder the sheet was laid out with. A sheet whose sections were never built answers zeros, which is what the counts are.

Returns: String. The counts as one phrase for the report line.


Errors

GuardNotSealed #

guard-not-sealed

Refuse a write to a creation-only binding after Create

Signature:

Private Sub GuardNotSealed(ByVal propName As String)

Parameters:

  • propName: String. The binding the caller tried to write.

Throws:

  • ProjectError.SomethingWentWrong When the instance is already sealed.

ThrowError #

throw-error

Raise a ProjectError-based exception

Signature:

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

Parameters:

  • errNumber: Long. The error code to raise.
  • errorMessage: String. Human-readable description of the failure.

Used in (12 file(s))