Odovzdáte hotový zošit kolegovi a chcete, aby ho filtroval, nie prepisoval. Takže hárok ochránite. V starších buildoch HotXLS tento krok zapísal do súboru jedinú vec: <sheetProtection sheet="1" objects="1" scenarios="1"/>, natvrdo zakaždým. Hárok sa uzamkol, pripojil sa hash hesla a používateľ nemohol vôbec nič, ani triedenie a filtrovanie, ktoré ste v skutočnosti chceli ponechať. Samotný dialóg Excelu "Protect Sheet" má presne z tohto dôvodu pätnásť zaškrtávacích políčok a engine nevedel vyjadriť ani jedno z nich. Túto medzeru uzatvára model ochrany vo verzii v2.91.0
HotXLS je natívny komponent VCL pre Delphi a C++Builder, ktorý číta a zapisuje XLS a XLSX bez nainštalovaného Excelu. Tento článok sa venuje strane ochrany hárka v XLSX: novému enumu TXLSXSheetProtectionOption, vlastnosti AllowOption, ktorá prepína jednotlivé oprávnenia, čo je jedinému pravidlu kódovania OOXML, na ktorom sa potkne každý, kto ručne zapisuje prvok <sheetProtection>
Čo ochrana hárka skutočne chráni
Najprv hranica, pretože od nej závisí, nakoľko tomu všetkému môžete veriť. Ochrana hárka vo formáte tabuliek OOXML (ECMA-376) nie je šifrovanie, ale politika interakcie. Hovorí kompatibilnej aplikácii, ktoré úpravy má odmietnuť, kým je hárok chránený. Hodnoty buniek stále ležia v xl/worksheets/sheetN.xml ako čistý text; rozbaľte .xlsx a sú tam. Voliteľné heslo je uložené ako krátky historický hash, nie ako kľúč, ktorý by čokoľvek zamiešal. Každý, kto súbor premenuje, otvorí danú časť a odstráni riadok <sheetProtection>, si všetko prečíta aj upraví
Ochrana teda rieši otázku „zabráň môjmu kolegovi, aby omylom prepísal vzorec“, nie „udrž tieto dáta v tajnosti pred motivovaným človekom“. To sú odlišné problémy a vyžadujú odlišné nástroje. Ak potrebujete dôvernosť, siahnite po šifrovaní na úrovni zošita, opísanom v článku AES-protected XLSX output, ktoré balík skutočne zašifruje. Ochrana hárka a šifrovanie zošita sa dajú čisto kombinovať, ale zámok je len to druhé. Keď si túto hranicu udržíte jasnú, zvyšok tejto stránky je už len potrubie
Pätnásť možností a vlastnosť AllowOption
Každý hárok teraz nesie množinu hodnôt TXLSXSheetProtectionOption opisujúcich, čo ešte môže používateľ robiť, keď je hárok chránený. Jednotlivé členy sa mapujú jedna k jednej na atribúty OOXML aj na zaškrtávacie políčka v dialógu Excelu:
xlsxSpoEditObjects,xlsxSpoEditScenariosupravovať kresliace objekty a scenáre what-ifxlsxSpoFormatCells,xlsxSpoFormatColumns,xlsxSpoFormatRowspreformátovať bunky, stĺpce a riadkyxlsxSpoInsertColumns,xlsxSpoInsertRows,xlsxSpoInsertHyperlinksvkladať stĺpce, riadky a odkazyxlsxSpoDeleteColumns,xlsxSpoDeleteRowsmazať stĺpce a riadkyxlsxSpoSelectLockedCells,xlsxSpoSelectUnlockedCellspresúvať výber na zamknuté alebo odomknuté bunkyxlsxSpoSort,xlsxSpoAutoFilter,xlsxSpoPivotTablestriediť rozsahy, používať rozbaľovacie ponuky AutoFilter a pracovať s PivotTables
Jednotlivé bity čítate a zapisujete cez indexovanú AllowOption vlastnosť na TXLSXWorksheet. AllowOption[Opt] = True znamená, že akcia je povolená; nastavenie na False ju zakáže. K celej množine sa dá pristupovať aj naraz cez SheetProtectionOptions, a TXLSXSheetProtectionOptions (obyčajné pascalovské set of), takže ju môžete uložiť, obnoviť alebo vymeniť ako celok
Predvolené nastavenie je dôležité a je zámerné: novovytvorený hárok začína so všetkými možnosťami povolenými. Konštruktor inicializuje SheetProtectionOptions celým rozsahom, [Low(TXLSXSheetProtectionOption)..High(TXLSXSheetProtectionOption)]. Odtiaľ už len vylúčite akcie, ktoré chcete zakázať, namiesto toho, aby ste množinu povolení budovali od nuly. Práve vďaka tomu sa nižšie uvedené pravidlo kódovania zapisovača zhoduje so správaním Excelu
Ochrana hárka s ponechaným triedením a filtrovaním
Tu je bežný prípad od začiatku do konca: ochráňte hotový report tak, aby sa nedal prestavať z hľadiska rozloženia, ale ponechajte čitateľovi triedenie a filtrovanie. Všimnite si, že Protect a možnosti sú nezávislé. Protect prepne hárok do chráneného stavu a uloží voliteľný hash hesla; množinu možností nemení. AllowOption upravujete samostatne a prepínače začnú platiť po ochrane a uložení hárka
var
wb: TXLSXWorkbook;
sh: TXLSXWorksheet;
begin
wb := TXLSXWorkbook.Create;
try
sh := wb.Sheets.Add('Protected');
sh.Cells[1, 1].Value := 'Region'; sh.Cells[1, 2].Value := 'Units';
sh.Cells[2, 1].Value := 'North'; sh.Cells[2, 2].Value := 120;
sh.Cells[3, 1].Value := 'South'; sh.Cells[3, 2].Value := 98;
// Protect with a password. This only sets the protected state + hash;
// the option set is left at its all-permitted default.
sh.Protect('HotXLS-2026');
// Narrow: keep sort + AutoFilter, forbid reshaping and reformatting.
sh.AllowOption[xlsxSpoSort] := True;
sh.AllowOption[xlsxSpoAutoFilter] := True;
sh.AllowOption[xlsxSpoFormatCells] := False;
sh.AllowOption[xlsxSpoFormatColumns] := False;
sh.AllowOption[xlsxSpoFormatRows] := False;
sh.AllowOption[xlsxSpoInsertRows] := False;
sh.AllowOption[xlsxSpoDeleteRows] := False;
if wb.SaveAs('protection.xlsx') <> 1 then
Writeln('SaveAs failed');
finally
wb.Free;
end;
end;
Zo snippetu si všimnite dve veci. Riadky Sort and AutoFilter sú zapísané explicitne, hoci obe majú predvolenú hodnotu True; to je dokumentácia pre ďalšieho správcu, nie funkčná požiadavka. A pretože predvolené nastavenia sú permisívne, jediné riadky, ktoré zmenia výstupný súbor, sú tie, ktoré nastavia možnosť na False. Nie je to náhoda tohto API, ale priamo sa tu ukazuje prenosový formát OOXML, čomu sa venuje ďalšia časť
Pravidlo kódovania: vynechanie znamená povoliť, attr=0 znamená zakázať
Toto je jediný naozaj neintuitívny fakt celej funkcie a presne na ňom sa ručne písaný <sheetProtection> zvyčajne pokazí. V OOXML je každý atribút pre jednotlivú akciu príznakom forbid a jeho neprítomnosť znamená povolenie. Chýbajúci atribút znamená, že akcia je dovolená. Atribút zapísaný ako "0" znamená, že počas ochrany hárka je akcia zakázaná. V dobre sformovanom súbore neexistuje formatCells="1" v zmysle „formátovanie je povolené“; atribút jednoducho vynecháte. (Predvolená hodnota chýbajúceho atribútu je boolovská predvolená hodnota OOXML true a tieto atribúty sú pomenované tak, že „true“ znamená, že príslušná úprava je povolená.)
Writer HotXLS to presne zrkadlí. Zapíše sheet="1" na zapnutie ochrany, potom prejde množinu možností a zapíše attr="0" iba pre tie možnosti, ktoré ste nastavili na False. Povolené akcie do výstupu nepridajú nič. Zošit z predchádzajúcej časti sa preto serializuje približne takto a nesie len zakázané akcie plus hash hesla:
// Conceptual output for the snippet above (attributes elided for brevity):
// <sheetProtection sheet="1"
// formatCells="0" formatColumns="0" formatRows="0"
// insertRows="0" deleteRows="0"
// password="...4-hex..."/>
// Note what is NOT there: no sort, no autoFilter, no selectLockedCells.
// Their absence is exactly what tells Excel those actions stay allowed.
Ak ste prišli od starého natvrdo zapísaného reťazca a čakali, že uvidíte každý atribút vypísaný explicitne, vyzerá to riedko, skoro nesprávne. Je to správne. Súbor, ktorý by uvádzal sort="1" and autoFilter="1", by pre kompatibilného čitateľa znamenal to isté, ale samotný Excel zapisuje minimálnu formu obsahujúcu iba zákazy a zhodné správanie drží diffy malé a round-trip nudný. Atribúty objects and scenarios sa riadia tým istým pravidlom: predvolene sú povolené, takže sa objavia len ako "0" vtedy, keď ich zakážete, čo je presný opak starého objects="1" scenarios="1", ktorý sa vypisoval bezpodmienečne
Čítanie ochrany späť: vernosť round-tripu
Model oprávnení, ktorý viete zapísať, ale nie prečítať, je jednosmerná ulica a typickým príznakom je cyklus načítanie-upravenie-uloženie, ktorý potichu rozšíri oprávnenia. HotXLS to uzatvára. Keď ParseWorksheetXml narazí na prvok <sheetProtection>, nastaví hárok ako chránený, zachytí hash hesla, ak je prítomný, a potom dekóduje každý atribút jednotlivých akcií späť do AllowOption podľa toho istého pravidla, ale obrátene: prítomný atribút s hodnotou "0" akciu zakáže; chýbajúci atribút ponechá možnosť na predvolenom povolenom stave
var
wb: TXLSXWorkbook;
sh: TXLSXWorksheet;
begin
wb := TXLSXWorkbook.Create;
try
wb.LoadFromFile('protection.xlsx');
sh := wb.Sheets[1]; // XLSX sheets are 1-based
if sh.IsProtected then
begin
Writeln('Protected; password hash present: ',
sh.SheetProtectHash <> '');
Writeln('Sort allowed: ', sh.AllowOption[xlsxSpoSort]);
Writeln('AutoFilter allowed: ', sh.AllowOption[xlsxSpoAutoFilter]);
Writeln('FormatCells allowed:', sh.AllowOption[xlsxSpoFormatCells]);
end;
finally
wb.Free;
end;
end;
Keď načítate súbor, ktorý writer vyrobil, dostanete Sort and AutoFilter späť ako True, FormatCells ako False, teda presne tú množinu, ktorú ste uložili. A práve o to ide: upravte jednu bunku v chránenom hárku s čiastočne ponechanými právami a znova ho uložte, a štrnásť oprávnení, ktorých ste sa nedotkli, prežije namiesto toho, aby sa zrútili späť do starého všetko-alebo-nič predvoleného správania
Praktické poznámky a limity
Pred zapojením do pipeline pre reporty sa oplatí vedieť niekoľko vecí:
- Heslo je z princípu slabé. Ochrana hárka XLSX ukladá 16-bitový historický hash, ten istý, ktorý Excel používa desaťročia, zachovaný kvôli interoperabilite. Bráni náhodným úpravám, ale neodolá útočníkovi. Nepovažujte ho za prostriedok na utajenie. Ak potrebujete skutočnú ochranu, zašifrujte zošit
- Nastavenie možností pred zapnutím ochrany je v poriadku.
AllowOptionmožno priradiť bez ohľadu na to, či je hárok práve chránený; prepínače len opisujú, čo ochrana dovolí, keď bude aktívneProtect.UnProtectzruší chránený stav aj hash, ale ponechá vašu množinu možností pripravenú na ďalšie použitie - Stále platí sémantika zamknutých buniek. Ochrana blokuje len úpravy buniek, ktorých atribút
Lockedje nastavený, čo je predvolené správanie zošita. Ak chcete ponechať vstupnú oblasť editovateľnú, rieši sa to štýlom buniek, nie voľbou ochrany; obe vrstvy sa kombinujú rovnako ako v Exceli - Toto je engine XLSX. Model možností zrkadlí staršie vlastnosti
Allow*v engine XLS, ale enum a názvy vlastností použité tu (xlsxSpo*,AllowOption) patria doTXLSXWorksheetinlxHandleX. Ak na tých istých hárkoch riadite aj tlačové rozloženie, článok prehľad ochrany a nastavenia strany vysvetľuje, ako tieto nastavenia sedia vedľa tlačových oblastí a hlavičiek, a článok validácia dát, AutoFilter a tabuľky sa prirodzene dopĺňa s ponechanímxlsxSpoAutoFilterotvoreného v uzamknutom reporte
Model jemnozrnnej ochrany a zvyšok XLSX engine na čítanie a zápis sú súčasťou HotXLS Component pre Delphi a C++Builder; produktová stránka obsahuje celé worksheet API vrátane kompletného referenčného prehľadu možností ochrany