ImportMetadata

Reads the variable and value block of the Metadata sheet of a workbook being imported, once, and answers every question the import has about that file. LoadFrom reads the sheet, Exists says whether the block is there, Tag answers one tag by name, and Language, ExportType, IsMigrationExport, EpiWeekStart and UpdatesOnImport answer the named facts. ExportOption reads one option of the options line, CarriesVariableNames says whether the file holds variable names, and HeaderRow says which row the header sits on.

ONE READ, AND NO Range.Find

The block is read into two arrays and every tag is looked up in memory. Four places used to build a DataSheet over this sheet and run a Range.Find with LookIn, SearchOrder and SearchDirection left unset. Excel fills those in from the last Find of the session, including one a user ran by hand.

THE OPTIONS LINE

export_options holds the options the export was written with, as name: value pairs joined with a pipe. ExportOption splits it back apart. The two pairs that decide whether the file can be read at all are variable names and header row: a file whose header row carries labels alone holds no variable names anywhere, and a file carrying both has its variable names on row 2.

A file written before the options line existed carries none of it. Every answer then falls back to the shape every export used to have, variable names on row 1, which is the shape of a migration export and of the default custom export.

Depends on: DataSheet, BetterArray, Checking

Version: 1.0 (2026-08-01)

Factory

Create #

create

Read the Metadata sheet of a workbook being imported

Signature:

Public Function Create(ByVal impwb As Workbook) As ImportMetadata

A workbook with no Metadata sheet gives an instance whose Exists answers False and whose every tag answers an empty string. That is a real case - a file exported with the metadata sheets switched off carries none - so it is answered rather than raised.

Parameters:

  • impwb: Workbook. The opened import workbook.

Returns: ImportMetadata. A ready instance.

Throws:

  • ProjectError.ObjectNotInitialized When the workbook is Nothing.

What the file says

Exists #

exists

Whether the file carries a Metadata sheet at all

Signature:

Public Property Get Exists() As Boolean

Returns: Boolean. True when the sheet was found and read.


Tag #

tag

The value of one tag of the Metadata sheet

Signature:

Public Property Get Tag(ByVal tagName As String) As String

The name is matched without regard to case, the way the Range.Find this replaced did. A tag the file does not carry answers an empty string.

Parameters:

  • tagName: String. The tag to read.

Returns: String. What the file holds for it, empty when it holds nothing.


Language #

language

The language the file was written in

Signature:

Public Property Get Language() As String

Returns: String. The language code, empty when the file names none.


ExportType #

export-type

What kind of export the file is

Signature:

Public Property Get ExportType() As String

Returns: String. "export for migrations" or "custom export: export N", empty when the file names neither.


IsMigrationExport #

is-migration-export

Whether the file is an export for migration

Signature:

Public Property Get IsMigrationExport() As Boolean

Returns: Boolean. True when the export type names a migration.


EpiWeekStart #

epi-week-start

The epiweek start day the file was written with

Signature:

Public Property Get EpiWeekStart() As String

Returns: String. The day number, empty when the file carries none.


UpdatesOnImport #

updates-on-import

Whether one tag asks the import to act on it

Signature:

Public Property Get UpdatesOnImport(ByVal tagName As String) As Boolean

show_hide and editable_labels are the two tags written this way. Both hold "update on import" or "no update on import".

Parameters:

  • tagName: String. The tag to read.

Returns: Boolean. True when the tag asks for an update.


The export options line

ExportOption #

export-option

One option of the line the export wrote

Signature:

Public Property Get ExportOption(ByVal optionName As String) As String

The pairs are split on the pipe and each pair on the first colon, so a value holding a colon of its own survives. An option the file does not carry answers an empty string, and the properties below turn that into the shape every export had before the line existed.

Parameters:

  • optionName: String. The option to read.

Returns: String. Its value, empty when the file carries no such option.


CarriesVariableNames #

carries-variable-names

Whether the data sheets of the file name their columns

Signature:

Public Property Get CarriesVariableNames() As Boolean

A file whose header row holds the labels a user reads carries no variable name anywhere, so no column of it can be matched to this linelist. A file written before the options line existed is taken as carrying them, which is what every export used to do.

Returns: Boolean. True when the columns can be matched.


HeaderRow #

header-row

The row of a data sheet that holds the variable names

Signature:

Public Property Get HeaderRow() As Long

Row 2 for a file written with labels above the names, row 1 for every other shape and for any file written before the options line existed.

Returns: Long. The 1-based row index.


Internal members (not exported)

Factory

LoadFrom #

load-from

Read the variable/value block into memory

Signature:

Public Sub LoadFrom(ByVal impwb As Workbook)

Public because the factory calls it on the instance it just made. A Private procedure cannot be reached by dotted access in VBA, so the factory could not fill the object at all.

Parameters:


Seal #

seal

Prevent further changes to setup-only members

Signature:

Public Sub Seal()

GuardNotSealed #

guard-not-sealed

Raise when a setup-only member is used after sealing

Signature:

Private Sub GuardNotSealed(ByVal memberName As String)

Parameters:


The export options line

ReadOptions #

read-options

Split the options line into names and values, once

Signature:

Private Sub ReadOptions()

Private - Error Handling

ThrowError #

throw-error

Raise a class level error

Signature:

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

Parameters:

Throws:


Used in (5 file(s))