Tehnični članak

HotXLS: Zaščita listov, nastavitev strani in tiskanje v Delphiju

Tri skupine nastavitev delovnega lista nimajo nikakršne zveze z vrednostmi celic in imajo vse opraviti s tem, kako se datoteka obnaša, ko zapusti vašo kodo. Zaščita lista določa, katere celice lahko uporabnik ureja po predaji delovnega zvezka. Nastavitev strani določa usmerjenost, velikost papirja in robove. Nastavitve tiskanja (ponavljajoče se vrstice z naslovi, prilagajanje velikosti in ročni prelomi strani) nadzorujejo, kako se mreža poljubne dolžine izpiše na papir. Nobena od teh treh skupin se ne pokaže, ko podatke opazujete v pregledovalniku, in vse tri tiho odpovejo v praksi, ko so napačne. HotXLS, domača knjižnica preglednic za Delphi in C++Builder, izpostavlja celotno površino za .xls in .xlsx, kar pomeni, da poustvarja tudi vsako protislovno Excelovo pravilo, vgrajeno vanjo

Prvo izmed teh pravil preseneti skoraj vsakogar, ko prvič zaščiti generirani list. Pokličete Protect in nenadoma nihče ne more pisati v nobeno celico, vključno z vhodnimi stolpci, okoli katerih ste zgradili delovni zvezek. Nič v vaši kodi se ni dotaknilo teh stolpcev in prav zato se to zgodi

Vsaka celica se rodi zaklenjena

Standard ECMA-376 definira lastnost locked as del zapisa o oblikovanju celice in ne kot lastnost same zaščite, privzeto pa je nastavljena na true. Zaščita lista je le stikalo, ki omogoča uveljavitev te zastavice. Tako celotna mreža nosi zastavico zaklepanja od trenutka, ko obstaja, speča, klic k Protect pa jih aktivira vse hkrati. Rešitev je v tem, da vrstni red določite načrtno: zgradite postavitev, eksplicitno odklenete obsege, ki jih morajo uporabniki urejati, in zaščitite na koncu

Diagram vrstnega reda zaščite HotXLS v Delphi, kjer se vsaka celica rodi z locked true, vhodni razponi se najprej odklenejo s SetLocked, nazadnje poklican Sheet.Protect pa ohrani odklenjene celice uredljive
Celice prispejo zaklenjene po privzetem, zato odklenite vhodne obsege najprej in pokličite Protect zadnje, da ostanejo uredljive
Book := TXLSXWorkbook.Create;
try
  Sheet := Book.Sheets.Add('Timesheet');
  // ... tukaj so zapisani vrstica z glavo, stolpec z imeni in formule za stopnjo ...
  Sheet.Range['B2:B50'].SetLocked(False);         // sem osebje vnaša ure
  Sheet.Range['F2:F50'].SetFormulaHidden(True);   // ohrani izračun stopnje zaseben
  Sheet.Protect('review-2026');                   // zdaj zastavice zaklepanja učinkujejo
  Book.SaveAs('timesheet.xlsx');
finally
  Book.Free;
end;

Metoda SetFormulaHidden počne nekaj ločenega in preprostega za spregledati: ko je zaščita aktivna, celica še vedno prikazuje svojo izračunano vrednost, vendar vrstica s formulami ne prikazuje ničesar. To je pomembno, ko formula vsebuje obračunske stopnje, marže ali uteži točkovanja, ki jih ne bi radi predali vsakemu prejemniku, ki klikne na skupno vsoto. Na fasadi XLS se isti namen izraža za vsak obseg prek IXLSRange.Locked in FormulaHidden. Delovni list tam nosi tudi petnajst zastavic Allow* (AllowSort, AllowAutoFilter, AllowFormatCells in ostale), tako da je zaščiten list še vedno mogoče razvrščati in filtrirati, namesto da bi bil zamrznjen v zaprto razstavo

Kaj geslo za zaščito dejansko ščiti

Oba formata shranjujeta geslo za zaščito lista in delovnega zvezka kot zapuščinsko zgoščeno vrednost s 4 šestnajstiškimi znaki. Šestnajst bitov pomeni, da z vsakim geslom trči nešteto nizov, orodja za odstranitev pa so le eno iskanje stran. Zaščito obravnavajte kot varnostni pas pred nenamernimi urejanji in ne kot nadzor dostopa. Je pravo orodje za preprečevanje, da bi ocenjevalci pisali prek stolpca s formulami, in napačno orodje za karkoli, kar vključuje besedo zaupno

Eno raven višje klic ProtectWorkbook na XLSX fasadi zaklene strukturo delovnega zvezka, kar preprečuje dodajanje, preimenovanje, brisanje ali preurejanje listov. Nastavite ga vedno, ko je seznam listov sam po sebi pogodba z uvoznikom v nadaljevanju, ki indeksira liste po imenu ali položaju. Preimenovan list pokvari uvoz na drugi strani prav tako zanesljivo kot izbrisan stolpec. Fasada XLS zrcali to plastenje s TXLSWorkbook.Protect na ravni delovnega zvezka in klici Protect za posamezne liste, poleg tega pa ponuja lastnost isProtected za kodo, ki mora pregledati podedovano datoteko, preden jo spremeni

Ko je zahteva dejanska zaupnost, se mehanizem popolnoma spremeni. Klic SaveAsEncrypted ustvari z AES šifriran paket pod shemo ECMA-376 Standard Encryption, kar je podrobneje opisano v priročniku za z AES zaščiten izhod XLSX, zapuščinska fasada XLS pa piše in bere z RC4 šifrirane datoteke .xls prek EncryptionPassword in preobremenitve z geslom metode Open. Razlika ni akademska. Zaščiten list potuje v čistem besedilu, zato lahko vsako orodje za zipanje prebere vrednosti njegovih celic, medtem ko je šifriran paket neberljiv brez gesla. Revizijska vrstica, ki pravi, da "mora biti datoteka za plače zaščitena", skoraj vedno pomeni šifriranje, ne glede na katero izrazoslovje uporablja

Diagram, ki protistavlja zaščiti listov HotXLS, ki shrani star 16-bitni razpršek in pusti vrednosti celic v čistem besedilu, berljive s katerim koli orodjem zip, z izhodom SaveAsEncrypted AES, ki ostane neberljiv brez gesla
Zaščita lista je varnostni pas proti naključnim urejanjem, medtem ko vrednosti v jasnem besedilu ostanejo berljive, le šifriranje AES pa skrije vsebino

Nastavitev strani je del pogodbe o dokumentu

Print behavior is invisible on screen, which is why it ships broken so often. The moment a customer prints the workbook, or exports it to PDF for an auditor, margins, scaling, and repeated titles turn into functional requirements that nobody tested. On the XLSX facade these settings hang directly off the worksheet:

Sheet.PageLandscape := True;
Sheet.PaperSize := xlsxPaperA4;
Sheet.SetPageMargins(0.5, 0.5, 0.75, 0.75, 0.3, 0.3);
Sheet.CenterHeader := 'Monthly Timesheet';
Sheet.RightFooter := 'Page &P of &N';
Sheet.PrintArea := '$A$1:$F$60';     // gola referenca: brez imena lista tukaj
Sheet.PrintTitleRows := '$1:$1';     // vrstica z glavo se ponovi na vsaki strani
Sheet.FitToWidth := 1;
Sheet.FitToHeight := 0;              // se širi navzdol, ko podatki rastejo
Sheet.PrintGridlines := False;

Dve od teh vrstic skrivata pasti. Nizi glave in noge uporabljajo Excelove kode za oblikovanje: &P za trenutno stran, &N za celotno število strani, z &L, &C in &R pa naslavljate tri dele posebej. Druga past je PrintArea, ki namenoma sprejme gol referenčni naslov celice. HotXLS jo shrani nekvalificirano in ji doda predpono z imenom lista, ko zapisuje datoteko, zato vaše posredovanje 'Timesheet!$A$1:$F$60' proizvede dvojno kvalificirano, popačeno referenco. Enako opozorilo velja raven nižje: območja tiskanja in naslovi tiskanja se shranijo kot vgrajena definirana imena _xlnm.Print_Area in _xlnm.Print_Titles, zato nikoli ročno ne dodajajte vnosov _xlnm.* prek zbirke DefinedNames, saj se bosta mehanizma borila za isto mesto

Prilagajanje velikosti, ki preživi produkcijske količine podatkov

Kombinacija FitToWidth := 1 in FitToHeight := 0 se bere kot "vedno prilagodi stolpce po širini na eno stran, nato pa vzemi toliko strani navzdol, kolikor podatki potrebujejo", in je pravilen privzeti nastavek za vsako poročilo, katerega število vrstic se spreminja. Past je prilagajanje fiksnega odstotka ali para za prilagajanje strani na tridesetvrstični testni datoteki: če enake nastavitve predate šestim stotim produkcijskim vrsticam, izhod bodisi eksplodira v ducat odrezanih strani bodisi se skrči pod mejo berljivosti. Prilagodite širino, pustite dolžini prosto pot in ponovite vrstico z glavo prek PrintTitleRows, da bo sedemnajsta stran še vedno berljiva sama po sebi

Diagram tiskalnega merjenja HotXLS v Delphi z FitToWidth, nastavljenim na 1, tako da vsaka stran ostane en list široka, FitToHeight na 0, tako da strani rastejo navzdol, PrintTitleRows, ki ponovi trak glave, in prelomi strani, znova ustvarjeni po ClearAllPageBreaks
FitToWidth 1 s FitToHeight 0 ohrani vsako stran en list široko, ponovljene naslovne vrstice in obnovljeni prelomi pa ohranijo berljivost

Ročni prelomi sledijo enaki disciplini regeneracije kot vse ostalo v ustvarjenem delovnem zvezku. Klic AddRowBreak(BeforeRow) začne novo stran pred mejo odseka, ko pa se generator znova zažene in se vrstice premaknejo, zastarel prelom pristane sredi tabele. Najprej pokličete ClearAllPageBreaks, nato pa znova dodajte prelome, izračunane iz generatorjevih lastnih števcev vrstic, namesto krpanja starih položajev. Na fasadi XLS enakovredne nastavitve živijo na Sheet.PageSetup (usmerjenost, velikost papirja, robovi, nizi glave in noge, prilagajanje strani), pri čemer RepeatRows in RepeatColumns pokrivata naslove tiskanja

Preverjanje rezultata, preden ga vidi stranka

Napake pri zaščiti in tiskanju imajo skupno lastnost: ročno jih je enostavno preveriti, a se skoraj nikoli ne preverijo. Odprite generirano datoteko v Excelu in ji namenite devetdeset sekund. Vpišite vrednost v vhodno celico in potrdite, da sprejme vnos; vpišite vrednost v zaklenjeno celico in potrdite, da se prikaže opozorilo o zaščiti; preverite, ali skrita formula pusti vrstico s formulami prazno. Neizogibno pa je preverjanje na predogledu tiskanja (Print Preview) nad produkcijsko količino podatkov in ne nad vzorcem s tridesetimi vrsticami, ter preberite število strani, ponavljajočo se vrstico z glavo in številčenje noge. Predogled je korak, ki se hitro obrestuje, saj je geometrija tiska odvisna od nastavitev brez zaslonskega izrisa, in razen fizičnega tiskalnika je to edino mesto, kjer napaka pri prilagajanju velikosti sploh postane vidna

Zadnja nastavitev dopolnjuje pregled. Klic FreezePane(ACol, ARow) ohranja blok z glavo v vidnem polju, medtem ko ocenjevalec drsi po strani. To je obnašanje zaslona in ne tiskanja, vendar ocenjevalec ocenjuje celoten izdelek hkrati. Delovni zvezek, ki začne svoje življenje kot postavitev, ki jo vzdržuje oblikovalec, večino tega dobi brezplačno: potek dela generiranja poročil na podlagi predlog ohrani nastavitve strani v predlogi, kjer jih je človek prilagodil za dejanski tiskalnik, kodi pa prepusti polnjenje podatkov in ponovno uveljavitev zaščite, ko se postavitev umiri

HotXLS je domača knjižnica preglednic v jeziku Object Pascal za Delphi in C++Builder; celotna referenca API za zaščito in nastavitev strani je na strani izdelka HotXLS Delphi Component