Razmotrite posao koji ne radi gotovo ništa: otvara mjesečnu radnu knjigu, zapisuje današnji datum u jednu ćeliju i ponovno je sprema. Pokrenite to kroz uslugu dovoljno često i pritužba će ipak stići. Makronaredbe su nestale ili povezani tečajevi valuta sada glase #REF!, a operativni tim je uvjeren da ih je vaš kod izbrisao. Nije izbrisao ništa. Ono što se obično dogodilo jest da je radna knjiga omogućena za makronaredbe poslana pod običnim .xlsx nazivom, a Excel je poslušao pravila o vrsti sadržaja ECMA-376: paket čija vrsta sadržaja ne deklarira VBA ne može učitati VBA projekt, bez obzira na to što se bajtovi fizički nalaze tamo. Datoteka se nije pokvarila. Preimenovana je u stanje u kojem je Excel dužan zanemariti dio nje.
Makronaredbe i vanjske veze radnih knjiga dvije su stvari koje automatizacija najpouzdanije gubi, iz istog temeljnog razloga. Obje žive izvan mreže ćelija koju kod za uređivanje zapravo dotiče, pa će ih kod koji razmišlja u okvirima redaka i stupaca odbaciti bez da ikada izda naredbu za brisanje. HotXLS je nativna Delphi i C++Builder biblioteka koja čita i piše XLS i XLSX bez instaliranog Excela, a oba resursa tretira kao terete koje namjerno nosi, a ne kao podatke koje slučajno kopira. U nastavku je opisano što je svakom od njih potrebno od vaše putanje spremanja i gdje jamstva prestaju.
Zašto se ova dva resursa ponašaju različito pod prepisivanjem
Zašto se ova dva resursa ponašaju različito pod prepisivanjem
VBA projekt je jedna neprozirna binarna datoteka. U OOXML paketu to je datoteka vbaProject.bin; u naslijeđenoj BIFF datoteci to je OLE pohrana. Postoje točno dva načina da se izgubi: pisac je nikada ne kopira u izlaz ili izlaz dobije vrstu datoteke koja to zabranjuje. Bilo koji neuspjeh je potpun i tih. Projekt je prisutan ili nije.
Vanjska poveznica uopće nije binarni objekt (blob). To je mali graf odnosa: ciljna putanja ili URL koji upućuje na drugu radnu knjigu, popis naziva listova koje taj cilj izlaže i izborne predmemorirane vrijednosti koje su zadnje viđene na tim listovima kako bi Excel mogao prikazati nešto kada je cilj izvan mreže. Ta tri dijela imaju različite životne vijeke pod prepisivanjem, a biblioteka može vjerno sačuvati neke dok druge tiho odbacuje. Ta asimetrija je dio o kojem vrijedi biti precizan jer je ništa u kodu za uređivanje ćelija neće otkriti.
Prenošenje VBA projekta kroz XLSX prepisivanje
Na XLSX strani, TXLSXWorkbook zadržava VBA teret doslovno. Svojstvo VbaProject drži sirove bajtove vbaProject.bin unutar niza AnsiString, a prazan niz je način na koji model kaže da nema makronaredbi. Oko njega sjede tri operacije: HasVbaProject odgovara je li projekt prisutan, ClearVbaProject ga namjerno uklanja, a LoadVbaProjectFromFile ubacuje projekt izvučen iz predloška. Taj posljednji poziv vrijedi više nego što izgleda. Omogućuje generiranim radnim knjigama da preuzmu standardni makro projekt bez provlačenja cijele datoteke predloška kroz cjevovod.
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Data');
Sheet.Cells[1, 1].Value := 'Refreshed ' + DateTimeToStr(Now);
Book.LoadVbaProjectFromFile('macros\vbaProject.bin');
if not Book.HasVbaProject then
raise Exception.Create('VBA payload failed to load');
// The .xlsm extension is not cosmetic: it selects the
// macro-enabled content type inside the package.
Book.SaveAs('monthly-report.xlsm');
finally
Book.Free;
end;
end;
Redak za spremanje je mjesto gdje se vrti cijeli problem. Radna knjiga koja sadrži VBA projekt mora biti zapisana sa semantikom omogućenom za makronaredbe, a HotXLS ih primjenjuje kada ciljni naziv završava na .xlsm. Predajte mu umjesto toga .xlsx i Excel odbija makronaredbe, iako su bajtovi fizički prisutni u paketu i u redu bi se deserijalizirali. Ekstenzija nije ukras; ona odabire vrstu sadržaja koja govori Excelu da je VBA projektu dopušteno postojati. Većinu vremena trebate samo prenijeti teret. Kada trebate čitati unutar njega, recimo da biste popisali nazive modula za revizijsko izvješće, ParsedVBAProject izlaže analizirani model modula, dok VbaProject ostaje izvorni netaknuti bajtovi.
Ponovna uporaba makronaredbi iz naslijeđenih XLS radnih knjiga
BIFF sučelje odražava taj skup alata uz jedan dodatni korak. HasVBAProject ispituje učitanu datoteku, SaveVBAProjectToFile piše pohranu projekta na disk, a LoadVBAProjectFromFile čita ga natrag u drugu radnu knjigu. Obilazak kroz datoteku čini uobičajeni zadatak modernizacije jednostavnim: podignite makronaredbe iz modela iz ere 2003. godine i posadite ih u svježe generirani XLS izlaz, bez potrebe za izvornim predloškom u vrijeme izvođenja.
var
Src, Dst: IXLSWorkbook; // interface references: no manual Free
begin
Src := TXLSWorkbook.Create;
if Src.Open('legacy-model.xls') <= 0 then
raise Exception.Create('Cannot open legacy model');
if Src.HasVBAProject then
Src.SaveVBAProjectToFile('extracted-vba.bin');
Dst := TXLSWorkbook.Create;
Dst.Sheets.Add.Name := 'Report2026';
Dst.LoadVBAProjectFromFile('extracted-vba.bin');
Dst.SaveAs('report-with-macros.xls');
end;
Memorijski model je ovdje zamka i radi suprotno od klase XLSX. TXLSWorkbook se drži kroz sučelje s brojenjem referenci IXLSWorkbook, pa ga nikada ne oslobađate ručno; XLSX TXLSXWorkbook je običan objekt koji morate omotati u try..finally i osloboditi. Pomiješajte te dvije konvencije u jednoj jedinici i uslijedit će padovi sustava zbog dvostrukog oslobađanja (double-free). Još jedna granica koju vrijedi poštovati: držite ekstrakciju i ubacivanje unutar jednog formata datoteke. BIFF pohrana projekta i OOXML vbaProject.bin su rođaci, a ne isti spremnik, i cjevovod koji mora emitirati makronaredbe u oba formata trebao bi zadržati zaseban makro predložak za svaki.`
Vanjske veze: karta preživljava, predmemorirane vrijednosti ne
Za XLSX radne knjige, HotXLS izlaže vanjske veze kroz zbirku ExternalLinks. Svaki TXLSXExternalLink nosi Target, putanju ili URL udaljene radne knjige, plus popis SheetNames koji imenuje listove na koje se odnosi. Oboje preživljava ciklus otvaranja i spremanja netaknuto, a također možete izgraditi vezu ispočetka:
var
Link: TXLSXExternalLink;
begin
Link := Book.ExternalLinks.Add('\\fileserver\finance\fx-rates-2026.xlsx');
Link.SheetNames.Add('FX');
if Book.ExternalLinks.Count > 0 then
Writeln(Format('%d external link(s): delivery requires reachable targets',
[Book.ExternalLinks.Count]));
end;
Granica se nalazi jednu razinu dublje od popisa ciljeva. HotXLS prenosi mapu veza u oba smjera, što znači cilj i nazive listova, ali ne analizira niti prepisuje predmemorirane vrijednosti ćelija koje OOXML čuva u elementu sheetDataSet veze. Ta predmemorija je ono što omogućuje Excelu da prikaže zadnji poznati broj kada je izvorna datoteka izvan mreže, a generirana radna knjiga se isporučuje bez nje. Posljedica pada na primatelja, a ne na vas. Otvorite takvu datoteku gdje je cilj nedostupan, prijenosno računalo izvan VPN-a ili dijeljeni resurs koji je preimenovan, i formule koje ovise o vezi razriješit će se u #REF! ili zapeti iza upita za ažuriranje. Dakle, iz ovoga proizlaze dva pravila. Nemojte obećavati da će generirana radna knjiga prikazivati svoje vanjski povezane vrijednosti izvan mreže. I čitajte ExternalLinks.Count različit od nule kao preduvjet isporuke, a ne kao značajku: svaki cilj mora biti dostupan s mjesta gdje će se datoteka stvarno otvarati.
Što XLS čitač čuva bajt-po-bajt
Prilagođeni prikazi, slike zaglavlja i zapisi tema prolaze kroz ciklus otvaranja i spremanja kao sirovi blokovi zapisa, neanalizirani i neizmijenjeni. Same vanjske reference kruže kroz temeljne zapise EXTERNSHEET i SupBook. Za njih ne postoji tipizirani API za stvaranje na XLS strani, ali postojeća veza preživljava uređivanje netaknuta.
Očuvanje bajt-po-bajt je pravo jamstvo s oštrim rubom. Budući da ništa ne čita očuvanu strukturu, vaše je izmjene ne mogu oštetiti. Iz istog razloga je ništa i ne ažurira. Umetnite retke kroz regiju na koju pokazuje sačuvana pivot predmemorija (pivot cache) ili tablica upita, i struktura zadržava svoje izvorne koordinate dok se podaci ispod nje pomiču. Datoteka je i dalje valjani XML ili BIFF; značenje je tiho ispalo iz usklađenosti i ne javlja se nikakva pogreška da vam to kaže. Izgled koji se može braniti jest držati generirana uređivanja na listovima koji ne sadrže sačuvane strukture, što je ista disciplina koja štiti zaključane listove i listove konfigurirane za ispis u našem članku o zaštiti radnih listova i postavljanju stranice.
Provjera datoteke koju ste stvarno zapisali
Oba načina kvara tiha su u vrijeme pisanja, stoga je tvrdnja koja je važna ona donesena ponovnim otvaranjem izlaza radije nego povjerenjem u kod koji ga je proizveo. Tri provjere pokrivaju gotovo sve. Ponovno otvorite datoteku i potvrdite da HasVbaProject i dalje vraća true kad god su se očekivale makronaredbe, što u jednom testu hvata odbačeni teret i pogrešnu ekstenziju. Pročitajte ExternalLinks.Count i usporedite ga s brojem prije prepisivanja. Zatim otvorite datoteku jednom u Excelu s onemogućenim makronaredbama jer je Excelova provjera valjanosti vrste sadržaja stroža od bilo koje biblioteke, a Excel je program po kojem će vaši kupci suditi o datoteci.
Ništa od toga ne zahtijeva potpunu analizu na ulazu. Kada radne knjige stižu u velikim količinama, a vi trebate samo trijažu koje od njih nose regulirani sadržaj, lagano ispitivanje u našem članku o izlistavanju listova i laganoj inspekciji radnih knjiga omogućuje vam usmjeravanje datoteka koje sadrže makronaredbe i veze u stroži cjevovod prije nego što se pokrene prvo prepisivanje.
VBA moduli unutar radne knjige moraju ostati inertni dok Excel ne otvori datoteku i korisnik ih ne pokrene. Na poslužitelju je to sigurnosno svojstvo koje vrijedi navesti jer neprijateljska makronaredba koja prolazi kroz cjevovod ostaje inertna sve dok stolni Excel ne otvori datoteku i korisnik ne omogući sadržaj. Pretvaranje .xlsm u .xlsx uz zadržavanje makronaredbi nije moguće, i to je pravilo formata, a ne ograničenje biblioteke: vrsta sadržaja .xlsx deklarira radnu knjigu bez makronaredbi, pa su jedini pošteni ishodi ostanak na .xlsm ili pozivanje ClearVbaProject i isporuka datoteke koja ih doista nema. Tiho preimenovanje je jedini izbor koji nikoga ne zadovoljava. A kada povezane ćelije prikazuju #REF! nakon prepisivanja, uzrok je nedostatak predmemorije vrijednosti o kojem se raspravljalo gore: nova datoteka nosi cilj, ali ne i predmemorirane brojeve, tako da Excel mora razriješiti izvor u vrijeme otvaranja, a nedostupna ili relativna putanja u odnosu na okruženje to onemogućuje. Ili zajamčite da je cilj dostupan ili upišite izračunate vrijednosti u ćelije prije isporuke i u potpunosti odbacite ovisnost.
Uređivanje tuđih radnih knjiga uglavnom je posao očuvanja stvari koje niste napisali i koje u potpunosti ne razumijete. Mogućnosti dvosmjernog putovanja VBA i vanjskih poveznica opisane ovdje dolaze s HotXLS komponentom za Delphi i C++Builder, zajedno sa svojstvima revizije koja vam omogućuju otkrivanje reguliranog sadržaja onog trenutka kada datoteka stigne.