Releases: minipoisson/xlsm_devkit
Releases · minipoisson/xlsm_devkit
v1.13.0
Added
- Testing harness: new optional module
src/devkit_Test.basplus a PowerShell runner that
treats a workbook like testable code. It generates boundary and random inputs into a work
copy and asserts that the result sheet stays free of Excel errors (no_errorproperty
check). All VBA API is non-interactive and uses JSON in/out (DevkitTestPing,
DevkitResolveInputs,DevkitApplyInputs,DevkitCalculateFullRebuild,
DevkitAssertNoErrors,DevkitWriteResult). Standard Windows PowerShell only -- no
Python or external modules.tools/Invoke-XlsmDevkitTest.ps1-- orchestrator (work copy, COM, generation, cleanup)tools/New-SampleTestWorkbook.ps1-- builds a sample workbook for verificationexamples/test-harness/tests/*.json+tests/fixtures/*.md-- meta/role,no_error
test, and fixture templatesTESTING.md-- harness reference; README (EN/JA) sections added- The module carries the
devkit_prefix, so it is auto-skipped on import/export and
stripped from released workbooks by existing machinery.
- Testing harness: sheet references now accept
code_name(VBA CodeName) in addition to
sheet(tab display name), disambiguating sheets whose tab names collide. The CodeName
takes priority when both are present;DevkitResolveInputsechoes both. - Testing harness: test fixtures (
DevkitApplyFixture). A test spec may seed cells with
values/formulas before the run via afixturesblock referencing a Markdown sheet-map
table (md_fileor inlinemd). Application is non-destructive (only listed cells are
written; no ClearContents/ClearFormats). Reuses the core Markdown helpers. - Testing harness: the work copy is placed under the workbook folder (
test-results/work)
instead of the system temp folder, so it inherits the workbook's Excel trusted location
(the system temp folder is usually not trusted, which blocks macros). The runner also
lowersApplication.AutomationSecurityfor the explicit local test copy.
Changed
xlsm_devkit.bas:ParseMDTableRowandUnescapeCellValueare nowPublicso optional
modules (e.g.devkit_Test) can reuse Markdown table parsing / cell-value unescaping.
No behavioural change to existing import/export.- Docs: testing-harness sections no longer carry an "experimental / Phase 1 MVP" label;
the full phase roadmap now lives inTESTING.md.
Fixed
InitDevModeand the import-complete dialog now localize theirMsgBoxtext viat()
(previously hardcoded English: "Failed to import component", "Success/Failed/Skipped"
labels). Newmsg.*keys added to all 27 language files.
v1.12.0
[1.12.0] - 2026-06-14
Fixed
ApplyCellStyle: boolean-attribute reset (Bold,Italic,Strike,Wrap,Unlocked) now runs for cells with empty style strings whenmerge=0. Previously the function exited before the reset block for empty-style cells, leaving existing Excel formatting unchanged when a token was removed from the Markdown. The reset now uses read-before-write: each attribute is read first and the write is skipped when the value already equals the desired default, minimising unnecessary COM writes.
v1.11.0
[1.11.0] - 2026-06-14
Fixed
ApplyCellStyle: when a boolean-attribute import flag is enabled (bold=1,italic=1,strike=1,wrap=1,unlocked=1), the corresponding attribute is now reset to its default value before token processing. Previously, if the token was absent from a cell's style string, the existing Excel value was left unchanged, causing drift whenmerge=0(sinceClearFormatsis skipped in that mode). Absence of a token is now treated as "restore default" for all enabled flags, consistent with export semantics (non-defaults only are emitted). Formerge=1the reset is redundant but harmless --ClearFormatsalready performs it.xlsm_devkit.ini/ README: corrected theunlocked=0comment which incorrectly stated "enable only together with merge=1". Therng.MergeArea.Lockedfix and lazy-unmerge introduced in v1.10.0 makeunlocked=1+merge=0fully safe. The default remains0as an opt-in safeguard against accidentally weakening sheet protection.
v1.10.0
[1.10.0] - 2026-06-14
Added
- Selective import write-back: place
xlsm_devkit.iniin the workbook folder with an[import]section to control which style categories are applied on import. Each key (value,formula,numfmt,unlocked,list,bg,fg,font_size,bold,italic,strike,wrap,halign,valign,merge,hidden_rows,hidden_cols,shapes) accepts0or1. Missing keys and a missing file both default to1for backward compatibility, exceptunlockedwhich defaults to0(see Changed below). Settingmerge=0skipsws.Cells.UnMergeentirely, eliminating the 8--15 minute bottleneck on sheets with thousands of merged regions. DisabledImportSettingsStr: new private helper; returns a space-separated list ofImportSettingsflags currently set toFalse(e.g."bg fg font_size ..."), or"(all enabled)"when all flags areTrue. Called at import start and logged viaLogImportDiagnosticso diagnostic logs show which categories are inactive.
Performance
ExportAllSheetMapsToMDnow setsScreenUpdating = False,Calculation = xlManual, andEnableEvents = Falseduring the export loop (same as import). This prevents screen repainting between cell reads, making export significantly faster for large sheets and ensuring the status bar progress message is visible.ImportAllSheetMapsFromMDskips sheets whose Markdown file has not changed since the last export or import. After each export/import the file size and modification time of every*.mdfile are written tosheet/xlsm_devkit_sync.tsv. On the next import run each file is compared against this cache; unchanged files are skipped entirely, reducing a full re-import of unmodified sheets to a near-instant check.
Changed
ImportUnlockednow defaults toFalse(previouslyTruevia the all-enabled backward-compatibility default). Settingrng.Locked = Falseon slave cells of still-merged ranges fails with Error 1004 whenmerge=0(UnMerge skipped). To applyUnlockedduring import, explicitly setunlocked=1inxlsm_devkit.ini; this works correctly only whenmerge=1is also set so cells are individually addressable after UnMerge.
Fixed
ExportAllSheetMapsToMDandImportAllSheetMapsFromMDnow callDoEventsinside the per-sheet loop so thatApplication.StatusBarprogress messages are repainted in real time. Previously the status bar was updated only after the loop completed, making progress invisible on large workbooks.ApplySheetMapMarkdownno longer raisesRPC_E_DISCONNECTEDon sheets with large merged regions afterws.Cells.UnMergecompletes. ADoEventscall immediately afterUnMergeflushes the COM message queue; an additionalDoEventsevery 1000 rows in Pass 1 prevents queue starvation on very large sheets.ApplyShapeFieldsno longer logs Err 438 for Picture-type shapes. Picture objects do not have a text frame; the label assignment is now guarded byshp.HasTextFrameand silently skipped instead of attempting the write and logging a spurious error.ApplyCellStyleno longer emitsWARN unknown style tokenfor recognized tokens that are disabled inxlsm_devkit.ini(e.g.bg=0suppressesBG:#rrggbbtokens that were incorrectly falling through to the WARN branch). Token name recognition is now separate from the cfg-flag check; known tokens with disabled flags are silently skipped. Only genuinely unknown tokens still produce a WARN.ApplyCellStyle:BOLD,ITALIC,STRIKE,WRAP, andUNLOCKEDtoken application is now guarded withOn Error Resume Next/On Error GoTo 0andLogImportDiagnosticerror logging, consistent withBG,FG,FONTSIZE,NUMFMT,HALIGN, andVALIGN. Previously, a runtime error in any of these five branches (e.g. Err 1004 fromrng.Locked = Falseon a slave cell of a merged range) would abort the entire import.DisabledImportSettingsStr: fixed a compile error --ReDim Preserveon a fixed-size array declared asDim parts(17) As Stringis not permitted; changed to a dynamic array with an initialReDim.ApplyCellStyle--UNLOCKEDtoken: changedrng.Locked = Falsetorng.MergeArea.Locked = False. Excel raises Err 1004 when setting.Lockedon any single-cell reference that belongs to a merged area (master or slave); usingMergeAreaaddresses the entire merged region and succeeds regardless of whetherrngis the master, a slave, or an individual cell.ApplyCellStyle: whenrngis a slave cell of a currently-merged region (can occur whenmerge=0leaves cells merged but the sheet map treats those cells as individual), the merge area is temporarily unmerged, all style tokens are applied, then the area is re-merged. This is a defensive preamble that protects all tokens; theUNLOCKEDfix above makes it specifically unnecessary for the Locked property, but it remains for other potential failures.
v1.9.0
[1.9.0] - 2026-06-11
Performance
ApplySheetMapMarkdownno longer freezes on sheets with thousands of merge slave cells (e.g. Sheet4 with 7357 lines and ~6000 slaves). Two additional COM-call bottlenecks eliminated:- Pass 1 slave handling called
ws.Range(addr)+ws.Cells(...).Address(...)per slave cell (~3 COM calls x ~6000 slaves = ~18 000 calls). Now usesAddrRowNum/AddrColNum/CellAddrStrpure string parsing -- zero COM calls per slave unless a named range must be applied. ReconstructMergescalledws.Rangeon every slave entry to read.Row/.Column(~18 000 COM calls for ~6000 slaves). Now uses the same string parsers and makes only onews.Range(...).Mergecall per distinct merge group.
- Pass 1 slave handling called
- New private helper:
CellAddrStr(r, c)-- inverse ofAddrRowNum/AddrColNum; converts row/column numbers back to an A1-style address string without touching the worksheet object model.
v1.8.0
[1.8.0] - 2026-06-11
Added
- Import progress:
Application.StatusBarshows "Importing sheet map N/N:<sheet>" duringImportAllSheetMapsFromMD; status bar is saved and restored even if an error occurs mid-import.
Fixed
ApplySheetMapMarkdownno longer freezes or disconnects COM on sheets with large merged regions. Two root causes were eliminated:- The per-cell cleanup loop built an
Application.Unionobject incrementally, causing O(n^2) slowdown and eventual COM disconnect (RPC_E_DISCONNECTED) on sheets with many cells outside the Markdown. ApplyCellStylewas called for every merge slave cell individually (~350+ calls on large sheets), even though slave styles are irrelevant afterReconstructMerges(master style propagates to the whole merged region).
- The per-cell cleanup loop built an
- Cleanup is now 3 batch operations on the Markdown bounding box (
ClearContents/ClearFormats/Validation.Delete). Merge slaves are recorded for Pass 2 only, with no per-cell style application. - Pass 0 bounding box calculation no longer makes COM calls (
ws.Range(addr)per address); replaced with pure string parsing helpersAddrRowNum/AddrColNum.
v1.7.0
Added
InitDevMode(.xlsx support): when the source workbook is.xlsx, the DEV_ copy is now created as.xlsm(macro-enabled format) instead of.xlsx. A temporary.xlsxfile is used internally during the copy+import step and deleted afterSaveAscompletes. This allowsCallInitDevModeto be used on.xlsxworkbooks that contain complex formulas or data, while still injecting the devkit VBA components correctly.
v1.6.0
Added
- Export progress:
Application.StatusBarshows "Exporting sheet map N/N:<sheet>" duringExportAllSheetMapsToMD; status bar is restored in alblFinhandler even if an export error occurs. NumFmt:<format>style token: exports the cell's number format (when it is notGeneral) and re-applies it on import (roundtrip).Unlockedstyle token: exportsrng.Locked = Falseand re-applies on import (roundtrip).HAlign:<value>/VAlign:<value>import-only style tokens: apply horizontal or vertical alignment when written manually in a sheet map (general,left,center,right,fill,justify,distributed, and numericXlHAlign/XlVAlignvalues are accepted; not exported).EscapeStyleValue/UnescapeStyleValue: new private helpers; extendEscapeCellValue/UnescapeCellValueby also escaping;as\;, allowing number-format strings that contain semicolons (e.g.#,##0.00;[Red]-#,##0.00) to round-trip correctly.\-escape sequence (\-decodes to-) added to bothUnescapeCellValueandUnescapeStyleValue; shape export now emits\-instead of the-sentinel when a shape label or OnAction string is the literal character"-".ParseStyleTokens: new private helper; splits style strings on unescaped;(respects\;).DevkitStringBuilderUDT withStringBuilderInit/StringBuilderAppend/StringBuilderToString; used inGenerateSheetMapMarkdownto build output in O(n) rather than O(n^2).IMPORT_DIAGNOSTICS_ENABLEDconstant (defaultFalse): when setTrue,StartImportDiagnosticLog/LogImportDiagnosticappend diagnostic events todevkit_import_diagnostics.log(FSO TextStream, one open/close per call for crash safety) in the workbook folder.AbortIfProtectedImportSheets: pre-import guard; shows a message and aborts if any target sheet is protected.ApplyShapeMapMarkdown: new private sub; reads the## Shapessection of a sheet map and applies label, formula, OnAction, and style back onto the worksheet (updates existing shapes by name, or creates a rectangle placeholder for shapes not found).
Changed
ApplyCellStyle: rewritten to useParseStyleTokens(escape-aware) instead ofSplit(styleStr, "; "); addsNumFmt,Unlocked,HAlign,VAlignhandling; errors during token application are now logged viaLogImportDiagnosticinstead of silently swallowed.GenerateSheetMapMarkdown: refactored to useDevkitStringBuilder; style-building extracted intoBuildCellStyle; shape labels, OnAction strings, and formula strings are now escaped withEscapeCellValue.ParseMDTableRow: rewritten to useTrimMDTableField(strips exactly one leading and one trailing space) instead ofTrimper field; preserves leading/trailing whitespace in cell values.ImportAllSheetMapsFromMD: now callsAbortIfProtectedImportSheetsbefore starting;ImportAllModulesFormsSheetMapsalso calls it in advance.
Fixed
- Export: cells containing error values (
#DIV/0!,#REF!, etc.) now exportrng.Textas a fallback instead of raising a runtime error. ExportAllSheetMapsToMD: addedlblErr/lblFinerror handler that restoresApplication.StatusBarandDisplayStatusBareven if an error occurs mid-export.ReconstructMerges,ApplyHiddenRows,ApplyHiddenCols: added per-operationOn Error Resume Nextguards withLogImportDiagnosticlogging so individual cell/row/column failures no longer abort the entire import.ApplySheetMapMarkdown: removed a redundantOn Error Resume Nextimmediately beforeOn Error GoTo 0in the pre-clear block.
v1.5.0
Added
InitDevMode: creates aDEV_<name>.xlsmcopy of the current workbook and imports alldevkit_*modules/forms found insrc/into it, enabling a clean dev/release separation workflow.SaveAsRelease: strips allxlsm_devkitanddevkit_*VBA components and saves a clean production copy (removesDEV_prefix from filename). Call from the DEV_ workbook.CallInitDevMode/CallSaveAsRelease: public entry-point wrappers callable from the Macro dialog (Alt+F8) or a Quick Access Toolbar button.btnSaveAsReleasebutton added todevkit_frmLauncher; enabled only when the workbook name starts withDEV_.btn_save_as_releasei18n key added to all 27 language files.ImportComponentIntoProject: private helper that imports a UTF-8 source file into any target VBProject (used byInitDevModefor cross-workbook injection).IsDevkitComponent: private helper that identifies devkit module names (used bySaveAsReleasefor stripping).- DEV/release workflow documented in README (English and Japanese).
- 11 new i18n keys (
init_*,release_*) added to all 27 language files.
Fixed
InitDevMode/SaveAsRelease: replacedAutomationSecurity = msoAutomationSecurityForceDisablewithEnableEvents = Falsewhen opening workbooks, preventing VBProject lockout that caused silent termination with no error raised.
v1.4.3
Added
msg.sheet_map_import_errorkey added to all 27 language files; displayed when
sheet map import fails mid-way.
Changed
StripAttributeLines: rewrote from O(n²) string concatenation loop to O(n)
array-join to avoid quadratic slowdown on large modules.LongArrayToRangeStr/ColNumArrayToLetterRangeStrconsolidated into
NumArrayToRangeStr+FormatNumRangeto eliminate duplicated range-formatting
logic.NormalizeStartUpPosition: parameter types widened fromIntegertoLong.
Fixed
ImportAllSheetMapsFromMD:Application.ScreenUpdating,Calculation, and
EnableEventsare now restored in an error handler so they are never left
disabled if the import fails mid-way.xlsm_devkit: addedIsErrorguard before reading cell values to prevent
runtime errors on cells containing error values (e.g.#REF!,#VALUE!).devkit_frmInsertDelete: addedm_syncLocktotxtCount_Changeto prevent
mutual re-entry withspnCount_Change(spinbutton ↔ textbox sync loop).devkit_frmInstruction: removed redundantIf MsgBox(...) = vbOKwrapper in
btnImport_Click; fixed parenthesizedMsgBox()call to statement form.devkit_frmLauncher:cboLang_Changenow callsSetLang ""uniformly for the
auto-detect entry (index 0) instead of branching onidx = 0.devkit_InsertDelete/devkit_Move: renamed local variablettotxtin
BuildInstructionText/BuildMoveInstructionTextto avoid shadowing the
globalt()i18n function.