CodeTransfer
Moves VBA code components -- classes, standard modules, forms and workbook code -- from a source workbook into a target workbook. A component is exported to a file in the temporary repository, imported into the target, and the file is deleted. TransferClass, TransferModule, TransferForm, TransferWorkbookCode and TransferWorksheetCode each move one component, and CopyModuleText copies the text of one module. Linelist.TransferAllCode is the one consumer, and it moves 39 components in a single generation.
A COMPONENT THE TARGET ALREADY HOLDS
VBComponents.Import stays quiet when the target already carries a component of that name: VBA imports the arriving one under a second name and keeps both copies, and the project stops compiling. Every transfer therefore removes the component that is already there before it imports, and files a warning through Checking naming it. The source copy is the one that survives, and a template author who wants their own code kept gives it another name. Owner decision, 2026-07-31.
THE VBA PROJECT HAS TO BE READABLE
Every member of this class reads a workbook's VBProject. Excel refuses that read with error 1004 while "Trust access to the VBA project object model" is off, and that is how a fresh install ships. SourceProject and TargetProject raise ErrorUnexpectedState naming the setting. Component lookups happen after that read, where a Nothing means the component is missing.
A CODE MODULE IS RESTORED WHEN A WRITE FAILS
Writing code into a component empties it first. The four writers keep the text they are about to replace and put it back when the write raises, so a failure leaves the target holding what it held before.
CHECKINGS NEED A HARVEST LINE
Entries filed here leave through HasCheckings and CheckingValues. Linelist keeps the instance after Prepare, and clickGenerate flushes the entries into the generation report.
Depends on: TemporaryRepos, Checking
Version: 1.1 (2026-07-31)
Instantiation
Create #
create
Create a CodeTransfer instance
Signature:
Public Function Create(ByVal sourceWkb As Workbook, _
ByVal targetWkb As Workbook, _
ByVal tempRepos As TemporaryRepos) As CodeTransfer
Factory method and Friend bindings for construction.
Creates a new CodeTransfer wired to transfer components from sourceWkb to targetWkb using tempRepos for intermediate file storage. All three parameters are validated as non-Nothing, and the instance is sealed before it is handed back, so the three bindings hold for its whole life.
Parameters:
sourceWkb: Workbook. The workbook containing the VBA components to export.targetWkb: Workbook. The workbook that will receive the imported components.tempRepos: TemporaryRepos. The temporary file repository for export/import.
Returns: CodeTransfer. A fully initialised instance ready for transfers.
Throws:
- ProjectError.ObjectNotInitialized When any parameter is Nothing.
Seal #
seal
Close the instance to creation-only writes
Signature:
Public Sub Seal()
Called by the factory once the three bindings are in place. Swapping the target workbook part way through a transfer would scatter components across two files, so the setters refuse a second write.
Operations
TransferClass #
transfer-class
Transfer a class module from source to target workbook
Signature:
Public Sub TransferClass(ByVal className As String)
Public methods for transferring VBA components.
Exports the named class module to a file called after the component, imports it into the target workbook, and deletes the file. A class of that name already in the target is removed first and the removal is filed through Checking.
Parameters:
className: String. The VBA component name of the class to transfer.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such class.
TransferModule #
transfer-module
Transfer a standard module from source to target workbook
Signature:
Public Sub TransferModule(ByVal moduleName As String)
Exports the named standard module to a file called after the component, imports it into the target workbook, and deletes the file. A module of that name already in the target is removed first and the removal is filed through Checking.
Parameters:
moduleName: String. The VBA component name of the module to transfer.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such module.
TransferForm #
transfer-form
Transfer a UserForm from source to target workbook
Signature:
Public Sub TransferForm(ByVal formName As String)
Exports the named UserForm to a .frm and a .frx called after the component, imports it into the target workbook, and deletes both files. A form of that name already in the target is removed first and the removal is filed through Checking. The .frx path is built by swapping the extension, which is what the VBIDE writes beside the .frm.
Parameters:
formName: String. The VBA component name of the form to transfer.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such form.
TransferWorkbookCode #
transfer-workbook-code
Copy code from a source module into the target's ThisWorkbook component
Signature:
Public Sub TransferWorkbookCode(ByVal moduleName As String)
Reads all code lines from the named module in the source workbook and writes them into the target workbook's ThisWorkbook code module, replacing what is there. The component is reached through Workbook.CodeName, which is where a workbook's own event code lives. The previous text is put back when the write raises.
Parameters:
moduleName: String. The source module whose code will be copied.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such module.
TransferWorksheetCode #
transfer-worksheet-code
Copy code from a source module into a worksheet's code module
Signature:
Public Sub TransferWorksheetCode(ByVal moduleName As String, ByVal targetSheetName As String)
Reads all code lines from the named module in the source workbook and writes them into the code module of the worksheet identified by targetSheetName in the target workbook, replacing what is there. The worksheet is looked up by its user-visible Name and its CodeName then locates the VBComponent, because the caller passes translated sheet names. Used to inject event handlers such as Worksheet_SelectionChange during linelist generation. The previous text is put back when the write raises.
Parameters:
moduleName: String. The source module whose code will be copied.targetSheetName: String. The user-visible name of the worksheet in the target workbook whose code module will receive the code.
Throws:
- ProjectError.ElementNotFound When the source module does not exist.
- ProjectError.ElementNotFound When the target worksheet does not exist.
CopyModuleText #
copy-module-text
Copy code text from a source module to an existing target module
Signature:
Public Sub CopyModuleText(ByVal moduleName As String)
Reads all code from the named module in the source workbook and writes it into the same-named module in the target workbook, replacing what is there. Both workbooks have to carry the module already: this member writes text into a component and creates none. Linelist calls it on the template branch, where the target workbook arrives with its own ribbon module. The previous text is put back when the write raises.
Parameters:
moduleName: String. The module name. It has to exist in both workbooks.
Throws:
- ProjectError.ElementNotFound When either workbook lacks the module.
Diagnostics
HasCheckings #
has-checkings
Whether anything was filed during the transfers
Signature:
Public Property Get HasCheckings() As Boolean
The Checking entries this instance filed, and how a caller reads them.
Returns: Boolean. True once one entry has been recorded.
CheckingValues #
checking-values
The diagnostic log of the transfers
Signature:
Public Property Get CheckingValues() As Object
Answers the internal Checking object holding every entry filed by this instance, and Nothing while none has been filed. The GenerationLog takes it through Linelist.
Returns: Object. A Checking instance, or Nothing.
Helpers
HasSourceComponent #
has-source-component
Whether the source workbook carries one component
Signature:
Public Function HasSourceComponent(ByVal componentName As String) As Boolean
For a component that is being added to the project and is not in every designer yet. The caller transfers it when it is there and files a note when it is not, so one designer without it still generates a linelist.
Parameters:
componentName: String. The component name to look for.componentName: String. The component to look for.
Returns: Boolean. True when the source workbook carries it.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such component.
Internal members (not exported)
Bindings
SourceWkb #
source-wkb
Assign the source workbook
Signature:
Friend Property Set SourceWkb(ByVal value As Workbook)
Friend setters used only during factory construction.
Parameters:
value: Workbook. The workbook the components are read from.
Throws:
- ProjectError.SomethingWentWrong When the instance is already sealed.
TargetWkb #
target-wkb
Assign the target workbook
Signature:
Friend Property Set TargetWkb(ByVal value As Workbook)
Parameters:
value: Workbook. The workbook the components are written into.
Throws:
- ProjectError.SomethingWentWrong When the instance is already sealed.
TempRepos #
temp-repos
Assign the temporary repository
Signature:
Friend Property Set TempRepos(ByVal value As TemporaryRepos)
Parameters:
value: TemporaryRepos. The folder the export files are written to.
Throws:
- ProjectError.SomethingWentWrong When the instance is already sealed.
Helpers
ExportImportComponent #
export-import-component
Export a VBA component from source and import it into target
Signature:
Private Sub ExportImportComponent(ByVal componentName As String, _
ByVal tempFileName As String)
Private utilities for export/import, code writing and error handling.
Exports the named component to a temporary file, removes any component of that name from the target, imports the file and deletes it. The temporary file is deleted again when any of those steps raises. Used by TransferClass and TransferModule.
Parameters:
componentName: String. The VBA component name to transfer.tempFileName: String. The temporary file name, extension included.
RemoveTargetComponent #
remove-target-component
Take a same-named component out of the target before an import
Signature:
Private Sub RemoveTargetComponent(ByVal targetProj As Object, _
ByVal componentName As String)
VBComponents.Import stays quiet on a name clash and leaves the target holding two copies under two names, which stops the project compiling. The copy that is there goes first, and the removal is filed as a warning so the generation report names it.
Parameters:
targetProj: Object. The VBProject of the target workbook.componentName: String. The component about to arrive.
SourceComponent #
source-component
The named component of the source workbook
Signature:
Private Function SourceComponent(ByVal componentName As String) As Object
Parameters:
componentName: String. The component to look for.
Returns: Object. The VBComponent.
Throws:
- ProjectError.ElementNotFound When the source workbook has no such component.
FindComponent #
find-component
Look a component up and answer Nothing when it is absent
Signature:
Private Function FindComponent(ByVal vbProj As Object, _
ByVal componentName As String) As Object
Parameters:
vbProj: Object. The VBProject to search.componentName: String. The component name to look for.
Returns: Object. The VBComponent, or Nothing.
SourceProject #
source-project
The VBProject of the source workbook
Signature:
Private Function SourceProject() As Object
Returns: Object. The VBProject.
Throws:
- ProjectError.ErrorUnexpectedState When Excel refuses the read.
TargetProject #
target-project
The VBProject of the target workbook
Signature:
Private Function TargetProject() As Object
Returns: Object. The VBProject.
Throws:
- ProjectError.ErrorUnexpectedState When Excel refuses the read.
ReadCode #
read-code
Read a whole code module into one string
Signature:
Private Function ReadCode(ByVal codeMod As Object) As String
One crossing for the whole module. Reading it line by line costs one crossing per line, so leave this as it is.
Parameters:
codeMod: Object. The CodeModule to read.
Returns: String. Every line of the module, and an empty string for an empty one.
ReplaceCode #
replace-code
Write text into a code module and put the old text back on a failure
Signature:
Private Sub ReplaceCode(ByVal codeMod As Object, ByVal codeContent As String)
DeleteLines 1, 0 on an empty module is what the line count guards against, and a workbook from Workbooks.Add carries an empty ThisWorkbook module. The text that is about to go is kept, so a raise between the delete and the write leaves the module holding what it held before.
Parameters:
codeMod: Object. The CodeModule to write into.codeContent: String. The text to write.
LogInfo #
log-info
Record a diagnostic entry, building the Checking object on first use
Signature:
Private Sub LogInfo(ByVal label As String, _
Optional ByVal scope As Byte = checkingNote)
Parameters:
label: String. The message to record.scope: Optional Byte. Severity from CheckingScope. Defaults to checkingNote.
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 (5 file(s))
- Linelist.cls
- HeadlessBuild.bas
- EventLinelistSheet.bas
- EventsLinelistButtons.bas
- TestCodeTransfer.bas