MasterSetupImportService
Internal members (not exported)
Factory
Create #
Build a service over the master setup workbook and its managers.
Signature:
Public Function Create(ByVal targetBook As Workbook, _
ByVal builder As DiseaseSheet, _
ByVal dropdowns As DropdownLists, _
ByVal variables As MasterSetupVariables, _
Optional ByVal choices As LLChoices = Nothing, _
Optional ByVal importer As DiseaseImporter = Nothing) As MasterSetupImportService
Parameters:
targetBook: Workbook. The master setup workbook receiving the import.builder: DiseaseSheet. Builds a disease sheet that is gone and puts the line formulas back after a merge.dropdowns: DropdownLists. The master dropdowns: the languages list and the diseases list.variables: MasterSetupVariables. The manager of the Variables table.choices: Optional LLChoices. The master Choices sheet; with none the lists of a file are left out and logged.importer: Optional DiseaseImporter. Defaults to a fresh importer.
Returns: MasterSetupImportService ready to import.
Configuration
Initialise #
Attach the workbook and the managers the imports write through.
Signature:
Public Sub Initialise(ByVal targetBook As Workbook, _
ByVal builder As DiseaseSheet, _
ByVal dropdowns As DropdownLists, _
ByVal variables As MasterSetupVariables, _
Optional ByVal choices As LLChoices = Nothing, _
Optional ByVal importer As DiseaseImporter = Nothing)
Setup Export Import
ImportSetupExport #
Fold a workbook exported for a setup back into the master setup.
Signature:
Public Function ImportSetupExport(ByVal sourceBook As Workbook, _
Optional ByVal logger As DiseaseLogger = Nothing, _
Optional ByVal diseaseName As String = vbNullString) As DiseaseImportSummary
The Metadata sheet is read first, then the Variables table takes the variables it lacks, the Choices sheet takes the lists it lacks, and the dictionary is staged as a disease table on a hidden sheet and landed on the disease worksheet. The staging sheet goes away on every path.
Parameters:
sourceBook: Workbook. The exported workbook, open.logger: Optional DiseaseLogger. Receives one line per variable and list added, and one warning per thing left out.diseaseName: Optional String. The name to use when the file carries none; it also wins over the one the file carries when given.
Returns: DiseaseImportSummary of the merge, or Nothing when no disease worksheet could take the block.
Disease Table Import
ImportDiseaseTable #
Land a table shaped as a disease table on the disease worksheet.
Signature:
Public Function ImportDiseaseTable(ByVal sourceTable As ListObject, _
ByVal diseaseName As String, _
ByVal languageTag As String, _
Optional ByVal restoreFormulas As Boolean = False, _
Optional ByVal logger As DiseaseLogger = Nothing) As DiseaseImportSummary
A worksheet of that name that is gone is built again, on the language given when the languages list carries it and on the default language otherwise; the block then replaces its table whole. A worksheet that is there is merged, with the imported values winning on the lines both carry. A worksheet of that name that is no disease worksheet is left alone and logged.
Parameters:
sourceTable: ListObject. Seven columns in the disease table order.diseaseName: String. Name of the disease worksheet.languageTag: String. Language the sheet takes when it is built.restoreFormulas: Optional Boolean. When True the label and the choice values formulas go back on every line once the values have landed, which is what a setup export wants: the master setup answers those two columns itself. A migration block keeps the values it carries.logger: Optional DiseaseLogger.
Returns: DiseaseImportSummary of the merge, or Nothing when the block was left out.
Name Resolution
ReadDiseaseName #
The disease name a file carries: its workbook tag, then its Metadata sheet.
Signature:
Public Function ReadDiseaseName(ByVal sourceBook As Workbook) As String
Returns: String, empty when the file names no disease.
DiseaseNameIsFree #
Whether a name can take a new disease worksheet in the target workbook.
Signature:
Public Function DiseaseNameIsFree(ByVal candidate As String) As Boolean
Empty names, names of a worksheet already there and names of the prohibited list are refused. A name already there would merge the file into a sheet the user did not name.
Results
AddedVariables #
Names of the variables the last import added to the Variables table.
Signature:
Public Property Get AddedVariables() As BetterArray
AddedChoices #
Names of the lists the last import added to the Choices sheet.
Signature:
Public Property Get AddedChoices() As BetterArray
DiseaseName #
Disease name read from the Metadata sheet of the last file.
Signature:
Public Property Get DiseaseName() As String
LanguageTag #
Language read from the Metadata sheet of the last file.
Signature:
Public Property Get LanguageTag() As String
DiseaseCode #
Disease code read from the Metadata sheet of the last file.
Signature:
Public Property Get DiseaseCode() As String
Metadata
ReadMetadata #
Settle the disease name, the language and the code of the file.
Signature:
Private Sub ReadMetadata(ByVal sourceBook As Workbook, ByVal givenName As String)
The workbook tags come first, the Metadata sheet fills what they leave empty, and a name given by the caller wins. A file with no name from any of the three is refused.
TagValue #
A workbook tag; a file with no hidden names store answers empty.
Signature:
Private Function TagValue(ByVal sourceBook As Workbook, ByVal nameId As String) As String
MetadataValue #
One value of the Metadata sheet, read by its label; empty without the sheet.
Signature:
Private Function MetadataValue(ByVal sourceBook As Workbook, ByVal metaLabel As String) As String
The Metadata sheet is a two-column block of labels and values, read by label so the order of the lines carries no weight.
Variables
UpdateVariables #
Add to the Variables table every variable of the dictionary it lacks.
Signature:
Private Sub UpdateVariables(ByVal dictionaryTable As ListObject, ByVal logger As DiseaseLogger)
One read of the dictionary block serves every line. A name the table carries, or one the file names twice, is passed over. The Default Choice column takes the list the variable points at, never the control itself: ChoiceNameAt settles which column of the file carries it.
ChoiceNameAt #
The list one dictionary line points at, whatever shape the file has.
Signature:
Private Function ChoiceNameAt(ByRef block As Variant, ByVal rowIndex As Long, _
ByVal controlColumn As Long, ByVal detailsColumn As Long) As String
With no "Control Details" column the file is one DiseaseExporter wrote, whose "Control" column already carries the list name, so that value is answered as it stands. With the column there the file is a setup dictionary: the control decides whether the details name a list at all, plain for choice_manual, choice_multiple and choice_custom and wrapped in CHOICE_FORMULA(...) for choice_formula. Every other control names none and answers empty, which leaves the Default Choice of the variable blank.
Parameters:
block: Variant. The dictionary block, headers on line 1.rowIndex: Long. The line to read.controlColumn: Long. Column of the control, 0 when the file has none.detailsColumn: Long. Column of the control details, 0 when the file has none.
Returns: String. The list name, empty when the line names none.
NormaliseControl #
A control read without its case and without a parenthesised tail.
Signature:
Private Function NormaliseControl(ByVal controlValue As String) As String
A setup writes "choice_manual" and also "choice_manual (something)"; both name the same control. This is the rule LinelistSpecs follows.
Parameters:
controlValue: String. The raw control cell.
Returns: String. The control, lower case and cut at the first bracket.
ChoiceFromFormula #
The list name held in a CHOICE_FORMULA(...) control details.
Signature:
Private Function ChoiceFromFormula(ByVal controlDetails As String) As String
The name is the first argument. The head, the closing bracket and anything past the first comma are dropped.
Parameters:
controlDetails: String. The raw control details cell.
Returns: String. The list name, empty when there is none.
RefreshAddedVariables #
Fill the joined choices values of the variables just added.
Signature:
Private Sub RefreshAddedVariables()
Only a default choice the Choices sheet carried before this import is joined: the labels of a list added by the same import sit where the user types them, and the label column follows once the sheet is edited.
Choices
UpdateChoices #
Add to the Choices sheet every list of the file it lacks, and fill the labels it lacks.
Signature:
Private Sub UpdateChoices(ByVal choicesTable As ListObject, ByVal logger As DiseaseLogger)
The labels travel only when the file is in English; otherwise the list lands with its name and its rows and every label empty. The choices ListObject of the master sheet, when there is one, is stretched over the rows added so the event handlers keep reading them. A list the sheet already carries is not added again, but its empty label cells are filled from an English file. That is the path back for a list added earlier from a file in another language, which lands with its rows and no label at all: the next English file naming the same list writes them. A cell that already holds a label, and a cell answering through a formula, are both left alone.
CollectListLabels #
Gather the labels of one list, in the order the file carries them.
Signature:
Private Sub CollectListLabels(ByRef block As Variant, _
ByVal listNameColumn As Long, _
ByVal listName As String, _
ByVal labelColumn As Long, _
ByVal translatedColumn As Long, _
ByVal rawColumn As Long, _
ByVal shortColumn As Long, _
ByVal keepLabels As Boolean, _
ByVal labels As BetterArray, _
ByVal shortLabels As BetterArray)
The label of a row is the label column when filled, then the translated label, then the non translated label. The short label falls back on the label. With keepLabels False both come out empty.
FillAbsentLabels #
Write the labels of the file into the empty label cells of a list already there.
Signature:
Private Sub FillAbsentLabels(ByRef block As Variant, _
ByVal listNameColumn As Long, _
ByVal listName As String, _
ByVal labelColumn As Long, _
ByVal translatedColumn As Long, _
ByVal rawColumn As Long, _
ByVal shortColumn As Long, _
ByVal logger As DiseaseLogger)
The rows of the list are matched by their position: the nth row of the list on the master sheet takes the nth label of the file. That is the order AddChoice wrote them in, so a list added from a file in another language lines up with the English file naming it later. Only a cell that is empty and holds no formula is written, so a label the user typed and a label answered by a formula both stand.
Parameters:
block: Variant. The choices block of the file, headers on line 1.listNameColumn: Long. Column of the list names in that block.listName: String. The list to fill.labelColumn: Long. Column of the label in the file, 0 when there is none.translatedColumn: Long. Column of the translated label in the file.rawColumn: Long. Column of the non translated label in the file.shortColumn: Long. Column of the short label in the file.logger: DiseaseLogger. Takes one line when a cell was written.
WriteWhenAbsent #
Write a value in a cell that holds nothing, and say whether it was written.
Signature:
Private Function WriteWhenAbsent(ByVal targetCell As Range, ByVal newValue As String) As Boolean
A cell carrying a formula answers its own value and is never written over, whatever that value comes to.
Parameters:
targetCell: Range. The cell to fill.newValue: String. The value to write; an empty one writes nothing.
Returns: Boolean. True when the cell took the value.
MasterLabelColumn #
The column of the master Choices sheet holding the labels.
Signature:
Private Function MasterLabelColumn() As Long
The translated label column wins when the sheet carries one; that is the column LLChoices.AddChoice writes, so the fill lands where the add would have.
Returns: Long. The worksheet column, 0 when the sheet carries neither.
MasterChoicesColumn #
One column of the master Choices sheet, found on its header row.
Signature:
Private Function MasterChoicesColumn(ByVal headerName As String) As Long
The header row is the start row of the LLChoices block and it is read from its start column rightwards until it runs out of headers.
Parameters:
headerName: String. The header to look for, matched without regard to case.
Returns: Long. The worksheet column, 0 when the sheet carries no such header.
StretchChoicesTable #
Stretch the choices ListObject over the rows AddChoice wrote under it.
Signature:
Private Sub StretchChoicesTable()
LLChoices writes below the last filled line and knows nothing of the table; the master event handlers read the sheet through the table.
Staging
BuildStagingTable #
Write the dictionary as a disease table on a hidden staging sheet.
Signature:
Private Function BuildStagingTable(ByVal dictionaryTable As ListObject) As ListObject
Seven columns in the disease table order. The order column takes the dictionary order when it is a number and the position of the line otherwise; the choice values column stays empty, its formula comes back once the block has landed. The Choice column of a disease table holds a list name, so it takes what ChoiceNameAt reads and never the control. A dictionary with no named line stages a header-only table.
OrderValue #
The dictionary order of a line when it is a number, its position otherwise.
Signature:
Private Function OrderValue(ByRef block As Variant, ByVal rowIndex As Long, _
ByVal orderColumn As Long, ByVal position As Long) As Variant
CountNamedRows #
Count the lines of a block carrying a variable name.
Signature:
Private Function CountNamedRows(ByRef block As Variant, ByVal nameColumn As Long) As Long
Disease Worksheet
BuildDiseaseSheet #
Build a disease sheet for an imported block.
Signature:
Private Function BuildDiseaseSheet(ByVal diseaseName As String, _
ByVal languageTag As String, _
ByVal logger As DiseaseLogger) As Worksheet
PurgeStaleDiseaseName #
Drop a diseases-list entry whose worksheet is gone.
Signature:
Private Sub PurgeStaleDiseaseName(ByVal diseaseName As String)
IsDiseaseSheet #
A disease worksheet is known by its hidden sheetTag.
Signature:
Private Function IsDiseaseSheet(ByVal targetSheet As Worksheet) As Boolean
Lookups
FindTable #
Find a ListObject by name anywhere in the workbook, then by sheet.
Signature:
Private Function FindTable(ByVal sourceBook As Workbook, _
ByVal tableName As String, _
ByVal sheetName As String) As ListObject
The exported tables carry the names a setup gives its own. A file edited by hand can have lost the table name and kept the sheet, so the first table of the named sheet is the fallback.
FindWorksheet #
Locate a worksheet by name without relying on implicit errors.
Signature:
Private Function FindWorksheet(ByVal targetBook As Workbook, ByVal sheetName As String) As Worksheet
TableBlock #
Read a ListObject with its header row as a two-dimensional block.
Signature:
Private Function TableBlock(ByVal table As ListObject) As Variant
HeaderColumn #
Column of a header in a block read with its header row, 0 when absent.
Signature:
Private Function HeaderColumn(ByRef block As Variant, ByVal headerName As String) As Long
CellAt #
Text of a block cell; a column of 0 reads as empty.
Signature:
Private Function CellAt(ByRef block As Variant, ByVal rowIndex As Long, ByVal columnIndex As Long) As String
DistinctValues #
Distinct values of one column of a block, in first-use order.
Signature:
Private Function DistinctValues(ByRef block As Variant, ByVal columnIndex As Long) As BetterArray
ContainsKey #
Whether a name has already been seen, without regard to case.
Signature:
Private Function ContainsKey(ByVal keys As BetterArray, ByVal key As String) As Boolean
TextOf #
Text of a cell value; an error value or an empty cell reads as empty.
Signature:
Private Function TextOf(ByVal cellValue As Variant) As String
IsEnglish #
A language tag starting with "en" is English.
Signature:
Private Function IsEnglish(ByVal languageTag As String) As Boolean
ResetTallies #
Start the tallies of a new import.
Signature:
Private Sub ResetTallies()
ErrorHandling
ThrowError #
Centralised error raising aligned with ProjectError codes.
Signature:
Private Sub ThrowError(ByVal errNumber As ProjectError, ByVal errMessage As String)
Used in (5 file(s))
- MasterSetupMigration.cls
- MasterSetupExports.bas
- TestMasterSetupExports.bas
- TestMasterSetupImportService.bas
- TestMasterSetupMigration.bas