Preimenovanje hardkodirane reference radnog lista u hiljadu obrazaca izveštaja sa makroima isključuje ručno otvaranje svake datoteke u VBA uređivaču. HotXLS rešava taj slučaj tako što izvorni kod VBA modula izlaže kao svojstvo SourceCode koje se može uređivati i svaku izmenu ponovo kompresuje algoritmom MS-OVBA, upisujući rezultat nazad u XLS, VBA projekat ili XLSM radnu svesku
Zašto tok VBA modula nije tekstualna datoteka
VBA modul nije izvorni tekst već mali binarni kontejner sa kešom performansi i izvornim tekstom obrađenim vlasničkom MS-OVBA kompresijom. Ta šema nije zip ni deflate, a ponovna kompresija je deo u kom pogrešan bit može proizvesti datoteku koju Excel odbija da otvori
Šta svojstvo SourceCode zaista menja u HotXLS-u
HotXLS predstavlja svaki VBA modul kao objekat TXLSVBAModule sa jednostavnim svojstvom SourceCode: WideString, a dodela nove vrednosti upravo je tako jednostavna: modul se u memoriji označava kao izmenjen i ništa ne dodiruje osnovni OLE tok dok se projekat ne sačuva. Sam projekat dolazi iz IXLSWorkbook.VBAProject u klasičnom XLS mehanizmu ili iz TXLSXWorkbook.ParsedVBAProject u OOXML mehanizmu sa makroima, pri čemu oba vraćaju TXLSVBAProject čiji se moduli nalaze iza indeksatora Item[] sa početkom od 1 i svojstva Count, pa je grupna izmena svakog modula u radnoj svesci samo petlja kroz celobrojni opseg
var
Wb: TXLSWorkbook;
Project: TXLSVBAProject;
I: Integer;
Updated: WideString;
begin
Wb := TXLSWorkbook.Create;
try
Wb.Open('MonthlyReport.xls');
if Wb.HasVBAProject then
begin
Project := Wb.VBAProject;
for I := 1 to Project.Count do
begin
Updated := StringReplace(Project[I].SourceCode,
'ReportSheet2025', 'ReportSheet2026', [rfReplaceAll]);
if Updated <> Project[I].SourceCode then
Project[I].SourceCode := Updated; // marks the module dirty
end;
Wb.SaveAs('MonthlyReport.xls'); // recompresses on write
end;
finally
Wb.Free;
end;
end;
Ta petlja je ujedno oblik revizijskog prolaza za proveru i konverziju radnih svezaka. Pre obrade hiljadu obrazaca, timovi žele da znaju koliko njih sadrži makroe i na šta se oni pozivaju — isti Project.Count ovde pokreće prepisivanje, a tamo postaje zbir makroa po datoteci
Unutar kontejnera za kompresiju MS-OVBA
Format kompresije MS-OVBA pakuje izvorne bajtove u CompressedContainer sa potpisom 0x01 i blokovima CompressedChunk do 4096 bajtova. Zaglavlje bloka nosi potpis, veličinu i CompressedChunkFlag, a tokeni mogu biti doslovni bajtovi ili CopyToken povratne reference; greška za jedan u širini bitova najčešći je problem ručne implementacije
Zašto HotXLS upisuje sirove blokove umesto uparenih tokena
HotXLS potpuno zaobilazi uparivanje tokena. Svaki izmenjeni blok zapisuje sa obrisanom zastavicom CompressedChunkFlag i doslovnim bajtovima, što je dozvoljeno u MS-OVBA. Kompromis se vidi u veličini datoteke, ne u ispravnosti, a Excel rezultat i dalje ispravno otvara
Šta HotXLS ostavlja nepromenjenim pri prepisivanju modula
Ponovna kompresija uvek zamenjuje samo deo toka modula. Svaki tok modula najpre čuva keš performansi, a zatim kompresovani izvorni kod, dok dir tok projekta u zapisu MODULEOFFSET precizno beleži gde se ta podela nalazi za svaki modul; HotXLS čita taj pomeraj, čuva svaki bajt pre njega tačno onako kako ga je pronašao i ponovo gradi samo kompresovani kontejner počev od tog pomeraja
Sam izvorni tekst prolazi kroz kodnu stranicu VBA projekta, a ne kroz UTF-8 — istu zastarelu kodnu stranicu kojom je Office prvobitno zapisao projekat. Izmena SourceCode koja uvede znakove izvan skupa te kodne stranice pri ponovnom kodiranju niske u bajtove u HotXLS-u tiho dobija zamenske znakove po principu najboljeg podudaranja, umesto da bude odbijena, pa je neuobičajen regionalni znak ubačen u komentar ili literal niske najverovatnije mesto na kom ćete primetiti gubitak. Spoljne reference i povezivanja biblioteka unutar istog projekta prate srodan, ali odvojen put očuvanja, opisan u pratećem članku o očuvanju spoljnih veza VBA, koji vredi pročitati pre nego što prolaz za prepisivanje obradi projekat povezan sa drugim radnim sveskama ili bibliotekama tipova
Kako prepisane makroe vraćate u radnu svesku
Nijedan poziv ne pokreće ponovnu kompresiju izričito — ona se automatski izvršava pri čuvanju. TXLSVBAProject.ApplyChanges obrađuje svaki izmenjeni SourceCode, dok TXLSWorkbook.SaveAs, TXLSXWorkbook.SaveAs i SaveVBAProjectToFile interno pokreću istu metodu
var
Wb: TXLSWorkbook;
begin
Wb := TXLSWorkbook.Create;
try
if Wb.LoadVBAProjectFromFile('LegacyMacros.ole') = 1 then
begin
Wb.VBAProject[1].SourceCode :=
StringReplace(Wb.VBAProject[1].SourceCode, 'OldServer', 'NewServer', [rfReplaceAll]);
Wb.SaveVBAProjectToFile('LegacyMacros_Patched.ole'); // ApplyChanges runs internally
end;
finally
Wb.Free;
end;
end;
var
Xlsx: TXLSXWorkbook;
Project: TXLSVBAProject;
begin
Xlsx := TXLSXWorkbook.Create;
try
Xlsx.Open('Dashboard.xlsm');
Project := Xlsx.ParsedVBAProject;
if Assigned(Project) then
begin
Project[1].SourceCode := StringReplace(Project[1].SourceCode,
'ConnStringV1', 'ConnStringV2', [rfReplaceAll]);
Xlsx.SaveAs('Dashboard.xlsm'); // SyncParsedVBAProject recompresses before the part is written
end;
finally
Xlsx.Free;
end;
end;
Sva tri odredišta u osnovi dele istu logiku SourceCode i ApplyChanges; jedina stvarna razlika među njima jeste poziv za čuvanje koji na kraju pokreće ponovnu kompresiju
Gde ovo i dalje može da zakaže
Dva načina otkaza treba predvideti pre rada nad produkcionim datotekama. Promena izvora poništava digitalni potpis VBA projekta i zahteva naknadno potpisivanje. Ručna ponovna implementacija kompresije može zbog jednog pogrešnog bita proizvesti datoteku koju Excel odbija, upravo zato je bezbednije koristiti postojeću strategiju upisa sirovih blokova
Za korišćenje ovoga nije potrebno obrnuto inženjerstvo formata. Delphi i C++Builder programeri dobijaju pristup čitanju i upisu svojstva SourceCode, ponovnu kompresiju usklađenu sa MS-OVBA i sva tri ovde opisana odredišta za upis kao deo standardne HotXLS Component, zajedno sa ostatkom njenog API-ja za klasične XLS i OOXML radne sveske