LLTranslation

Manages the translation ListObjects that sit on one worksheet and hands out a TranslationObject per scope. TransObject answers the object of one scope, Refresh drops what is held, Import and Export move whole translation tables between workbooks, ImportDictionary and ExportDictionary move the setup translation table on its own, and InitialiseHiddenNames writes the translated configuration values into a workbook as hidden names.

WHAT THE FIVE TABLES HOLD

Four of them translate the linelist itself: T_TradLLMsg the messages, T_TradLLShapes the button captions, T_TradLLForms the form labels and T_TradLLRibbon the ribbon labels.

Tab_Translations is the SETUP's translation table, which is a different thing from the linelist dictionary. The setup file carries it, InitTransfer copies it onto the linelist's copy of this worksheet while the linelist is being built, and it is what translates the dictionary, the choices and the analyses. ImportDictionary is the copy in and ExportDictionary the copy out: a data export from a linelist carries this table on its own.

THE FIVE TABLES ARE ALL REQUIRED

Create asks for all five. The designer template ships every one of them, so a sheet missing one is a broken sheet and the failure is raised at creation.

WHERE THE LANGUAGES LIVE

The two language codes live in workbook-level hidden names, RNG_LLLanguageCode and RNG_DictionaryLanguage, on the workbook that holds the translation worksheet. TransObject reads them there and raises when the code it needs is empty.

WHAT IS HELD IN MEMORY

The hidden name store and the five scoped TranslationObjects are built once per instance. Building the store walks every Name of the workbook, and each TranslationObject holds its own copy of its table, so a caller that keeps this instance keeps both. Refresh drops all of them. The two import routines drop the scoped objects themselves, and a caller that writes into a translation table by any other route calls Refresh.

Depends on: TranslationObject, CustomTable, HiddenNames, Checking

Version: 1.2 (2026-07-30)

Factory

Create #

create

Create a new LLTranslation from a translation worksheet

Signature:

Public Function Create(ByVal translationSheet As Worksheet) As LLTranslation

Instance creation via VB_PredeclaredId factory pattern.

Validates that the worksheet is not Nothing and that all five translation ListObjects are present (T_TradLLMsg, T_TradLLShapes, T_TradLLForms, T_TradLLRibbon, Tab_Translations).

Parameters:

  • translationSheet: Worksheet. The worksheet hosting all translation ListObjects.

Returns: LLTranslation. A facade over the five tables.

Throws:

  • ProjectError.ObjectNotInitialized When translationSheet is Nothing.
  • ProjectError.ElementNotFound When a required ListObject is missing.

Properties

Wksh #

wksh

Host translation worksheet

Signature:

Public Property Get Wksh() As Worksheet

Accessors for translation objects and the host worksheet.

Returns the worksheet bound to this instance.

Returns: Worksheet. The host translation worksheet.


TransObject #

trans-object

Scoped translation object

Signature:

Public Property Get TransObject(Optional ByVal trans As Byte = TranslationOfMessages) As TranslationObject

Returns a TranslationObject configured for the requested translation scope. The language code is resolved from the hidden names of the workbook holding the translation worksheet: RNG_DictionaryLanguage for the dictionary scope and RNG_LLLanguageCode for the other four.

Each scope is built once and kept. Refresh drops the five.

Parameters:

  • trans: Optional Byte. TranslationScope value selecting the content scope. Defaults to TranslationOfMessages.

Returns: TranslationObject. The translation object for the requested scope.

Throws:

  • ProjectError.InvalidArgument When the scope is outside the enum.
  • ProjectError.ElementNotFound When the requested ListObject is absent from the host worksheet, or when the language code the scope needs is empty.

Refresh #

refresh

Drop everything this instance holds in memory

Signature:

Public Sub Refresh()

Clears the hidden name store and the five scoped translation objects, so the next read builds them again. Call it after a name is deleted and added back on the workbook, and after writing into a translation table by any route other than this class.


DataExchange

Export #

export

Export all translation tables to an output workbook

Signature:

Public Sub Export(ByVal outputWkb As Workbook, _
                  Optional ByVal Hide As Long = xlSheetVeryHidden)

Import, export, and dictionary exchange operations.

Creates or empties a worksheet in the output workbook matching the host sheet name, then exports every ListObject from the host sheet using CustomTable.Export with stacking. Formats the used range and sets the sheet visibility to the Hide parameter value.

Tab_Translations is written LAST, under the other four. InitTransfer overwrites it with the setup's own table as soon as the sheet has arrived, and CustomTable.Import writes the incoming rows over the cells below the table rather than inserting them. Anywhere but the bottom of the stack, a setup table with more rows than the designer carries would land on the table below.

Parameters:

  • outputWkb: Workbook. The destination workbook.
  • Hide: Optional Long. Sheet visibility after export. Defaults to xlSheetVeryHidden.

Throws:

  • ProjectError.ObjectNotInitialized When outputWkb is Nothing.

Import #

import

Import translation tables from another workbook

Signature:

Public Sub Import(ByVal fromWkb As Workbook)

Finds the worksheet in the source workbook carrying the host sheet name, and for each ListObject on the host sheet imports the data of the matching ListObject on that source sheet. A table the source does not carry is left standing.

Tab_Translations used to be emptied here before the loop had discovered whether the source carried a replacement, and it was emptied through a CustomTable with no key column, which takes the tag column with the rest. A source without Tab_Translations left the setup translations blank with nothing to write them back.

Parameters:

  • fromWkb: Workbook. The source workbook containing translation data.

Throws:

  • ProjectError.ObjectNotInitialized When fromWkb is Nothing.
  • ProjectError.ElementNotFound When the source workbook carries no worksheet of the host sheet name.

ImportDictionary #

import-dictionary

Take the setup translation table onto the host worksheet

Signature:

Public Sub ImportDictionary(ByVal dictionaryTable As ListObject)

Overwrites Tab_Translations with the supplied ListObject, which is the translation table of the setup file. The host table takes the source column headers with keepSourceHeaders, so it comes out carrying the language columns the setup carries. InitTransfer calls this on the LINELIST's translation sheet while the linelist is being built, and what lands here is what translates the dictionary, the choices and the analyses. The designer's own translation sheet is never written this way: its four linelist tables are maintained by hand, through the designer's import button.

Parameters:

  • dictionaryTable: ListObject. The setup translation ListObject.

Throws:

  • ProjectError.ObjectNotInitialized When dictionaryTable is Nothing.
  • ProjectError.ElementNotFound When the host dictionary table is not found.

ExportDictionary #

export-dictionary

Write the setup translation table onto a worksheet of an output workbook

Signature:

Public Sub ExportDictionary(ByVal outputWkb As Workbook, _
                            Optional ByVal sheetName As String = "Translations", _
                            Optional ByVal Hide As Long = xlSheetVisible)

Creates or empties a worksheet in the output workbook with the given name, then exports Tab_Translations using CustomTable.Export. Formats the used range and sets the sheet visibility.

LLExporter calls this when a user exports data out of a linelist. Of the five tables, this is the one that travels: it is what lets the exported dictionary and choices still be read in the language the user picked.

Parameters:

  • outputWkb: Workbook. The destination workbook.
  • sheetName: Optional String. Worksheet name for the export. Defaults to "Translations".
  • Hide: Optional Long. Sheet visibility after export. Defaults to xlSheetVisible.

Throws:

  • ProjectError.ObjectNotInitialized When outputWkb is Nothing.
  • ProjectError.ElementNotFound When the host dictionary table is not found.

HiddenNames

InitialiseHiddenNames #

initialise-hidden-names

Create RNG_ hidden names on a target workbook*

Signature:

Public Sub InitialiseHiddenNames(ByVal targetWkb As Workbook)

Workbook-level hidden name initialisation from translations.

Translates message and sheet-name tags using the TranslationOfMessages scope, then writes each translated value as a workbook-level hidden name on the target workbook. The three language names are left alone: they are written by InitTransfer and by Linelist before this runs.

When the target workbook is the one holding the translation worksheet, the store this instance already carries is used, which saves a second walk over the same Names collection.

Parameters:

  • targetWkb: Workbook. The workbook receiving the hidden names.

Throws:

  • ProjectError.ObjectNotInitialized When targetWkb is Nothing.

Internal members (not exported)

Factory

Seal #

seal

Seal the instance against further creation-only writes

Signature:

Public Sub Seal()

InternalSheet #

internal-sheet

Friend setter for the host worksheet

Signature:

Friend Property Set InternalSheet(ByVal value As Worksheet)

Used by the factory method during construction. Writing to it after Create raises, so the cached hidden name store and the cached translation objects can never point at a worksheet the instance has given up.

Parameters:

Throws:


WorkbookNames #

workbook-names

The hidden name store of the workbook holding the translations

Signature:

Private Function WorkbookNames() As HiddenNames

Built once per instance. Building one walks every Name of the workbook.

Returns: HiddenNames. The workbook-level store.


Internal Helpers

BuildScope #

build-scope

Build the translation object of one scope

Signature:

Private Function BuildScope(ByVal tableName As String, _
                            ByVal langNameId As String) As TranslationObject

Private utility methods.

Resolves the table and the language code the scope needs, and raises when the code is empty. An empty code gives a TranslationObject whose language matches no column header, and every tag then translates to itself with no error raised anywhere below it.

Parameters:

Returns: TranslationObject. The translation object for that table.

Throws:


DropScopeCache #

drop-scope-cache

Forget the five scoped translation objects

Signature:

Private Sub DropScopeCache()

Each one holds a copy of its table, so anything that rewrites a table has to drop them.


ResolveListObject #

resolve-list-object

Resolve a ListObject by name from the host worksheet

Signature:

Private Function ResolveListObject(ByVal tableName As String) As ListObject

Returns the ListObject with the given name from the host translation worksheet. Raises an error when the table is not found.

Parameters:

Returns: ListObject. The resolved table.

Throws:


FindOrCreateSheet #

find-or-create-sheet

Find or create a worksheet in the target workbook

Signature:

Private Function FindOrCreateSheet(ByVal targetWkb As Workbook, _
                                   ByVal targetName As String) As Worksheet

Finds the worksheet of the given name in the target workbook. When it is there, its tables are deleted and its cells cleared; when it is absent, a worksheet of that name is added at the end.

Clearing cells leaves the ListObject objects standing, and each one keeps its name. The export that follows adds tables under those same names, so a second export into one workbook used to meet a name Excel had already given out and raise 1004.

Parameters:

Returns: Worksheet. The resolved or newly created worksheet.


FormatExportSheet #

format-export-sheet

Apply standard formatting to an exported sheet

Signature:

Private Sub FormatExportSheet(ByVal sh As Worksheet, ByVal Hide As Long)

Sets font and alignment over the used range, autofits it, then sets the sheet visibility.

The look of the sheet is cosmetic and a failure there is suppressed. The visibility write is not cosmetic and stands outside the suppression: Excel refuses to hide the last visible worksheet of a workbook and refuses a write to a protected workbook structure, and either one leaves the translation tables on show in a delivered linelist.

Parameters:


CheckRequirements #

check-requirements

Validate that the translation sheet has all required tables

Signature:

Private Sub CheckRequirements(ByVal translationSheet As Worksheet)

Ensures the worksheet is not Nothing and that all five translation ListObjects are present.

Parameters:

Throws:


HiddenName writing

EnsureAndSet #

ensure-and-set

Give a HiddenName its value, creating it when it is absent

Signature:

Private Sub EnsureAndSet(ByVal store As HiddenNames, ByVal nameId As String, _
                         ByVal value As String)

Creating a hidden name and giving it its value.

EnsureName writes the value only when it creates the name, so a name that is already there needs the SetValue. Creating one and setting it straight after costs a full RefersTo rewrite and a comment re-apply on every one of the 17 names, which is why the two are branches here.

Parameters:


Error Handling

ThrowError #

throw-error

Raise a ProjectError-based exception

Signature:

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

Centralised error raising.

Parameters:


Used in (24 file(s))