Sodelavcu predate dokončan delovni zvezek in ga prosite, naj ga filtrira, ne pa prepiše. Zato zaščitite list. V starejših gradnjah HotXLS je ta gesta v datoteko vedno zapisala eno samo stvar: <sheetProtection sheet="1" objects="1" scenarios="1"/>, trdo kodirano, vsakič. List se je zaklenil, pripel se je zgoščeni zapis gesla, uporabnik pa ni mogel narediti prav ničesar, niti razvrščanja in filtriranja, ki ste ga želeli pustiti odprtega. Excelovo pogovorno okno Protect Sheet ima prav zato petnajst potrditvenih polj, pogon pa ni znal izraziti niti enega od njih. To vrzel zapre zaščitni model iz v2.91.0
HotXLS je izvorna komponenta VCL za preglednice za Delphi in C++Builder, ki bere in zapisuje XLS in XLSX brez nameščenega Excela. Ta članek govori o strani zaščite delovnega lista v XLSX: o novem enumu TXLSXSheetProtectionOption, lastnosti AllowOption, ki preklaplja posamezna dovoljenja, in o enem pravilu kodiranja OOXML, ob katerem se spotakne vsak, ki element <sheetProtection> piše na roke
Kaj zaščita delovnega lista dejansko varuje
Najprej meja, ker od nje je odvisno, koliko smete vsemu temu zaupati. Zaščita delovnega lista v obliki OOXML za preglednice (ECMA-376) je politika interakcije, ne šifriranje. Skladni aplikaciji pove, katere spremembe mora zavrniti, ko je list zaščiten. Vrednosti celic še vedno ležijo v xl/worksheets/sheetN.xml kot navadno besedilo; razpakirajte .xlsx in tam so. Neobvezno geslo je shranjeno kot kratek podedovani hash, ne kot ključ, ki bi karkoli premešal. Kdor preimenuje datoteko, odpre del in odstrani vrstico <sheetProtection>, lahko vse bere in ureja
Zato zaščita odgovarja na vprašanje "prepreči sodelavcu, da bi po nesreči povozil formulo", ne pa "ohrani te podatke skrivne pred nekom, ki je odločen". To sta različna problema z različnimi orodji. Če potrebujete zaupnost, želite šifriranje na ravni delovnega zvezka, opisano v izpisu XLSX, zaščitenem z AES, ki paket dejansko šifrira. Zaščita lista in šifriranje delovnega zvezka se lepo dopolnjujeta, toda le drugo je prava ključavnica. Če to mejo držite jasno, je preostanek te strani le še napeljava
Petnajst možnosti in lastnost AllowOption
Vsak delovni list zdaj nosi množico vrednosti TXLSXSheetProtectionOption, ki opisujejo, kaj uporabnik še sme početi, ko je list zaščiten. Člani se ena proti ena preslikajo v atribute OOXML in v potrditvena polja Excelovega pogovornega okna:
xlsxSpoEditObjects,xlsxSpoEditScenarios- urejanje predmetov risbe in scenarijev what-ifxlsxSpoFormatCells,xlsxSpoFormatColumns,xlsxSpoFormatRows- preoblikovanje celic, stolpcev, vrsticxlsxSpoInsertColumns,xlsxSpoInsertRows,xlsxSpoInsertHyperlinks- vstavljanje stolpcev, vrstic, povezavxlsxSpoDeleteColumns,xlsxSpoDeleteRows- brisanje stolpcev, vrsticxlsxSpoSelectLockedCells,xlsxSpoSelectUnlockedCells- premikanje izbire na zaklenjene ali odklenjene celicexlsxSpoSort,xlsxSpoAutoFilter,xlsxSpoPivotTables- razvrščanje obsegov, uporaba spustnih seznamov AutoFilter in delo z vrtilnimi tabelami
Posamezne bite berete in zapisujete prek indeksirane lastnosti AllowOption na TXLSXWorksheet. AllowOption[Opt] = True pomeni, da je dejanje dovoljeno; če ga nastavite na False, je prepovedano. Do celotne množice lahko dostopate tudi naenkrat prek SheetProtectionOptions, ki je TXLSXSheetProtectionOptions (navaden Pascalov set of), zato ga lahko shranite, obnovite ali v celoti zamenjate
Privzeta vrednost je pomembna in namerna: na novo ustvarjen delovni list začne z dovoljenimi vsemi možnostmi. Konstruktor inicializira SheetProtectionOptions s celotnim obsegom, [Low(TXLSXSheetProtectionOption)..High(TXLSXSheetProtectionOption)]. Od tam ga ožite z izključevanjem dejanj, ki jih želite prepovedati, namesto da bi množico dovoljenj gradili od nič. Ta odločitev je razlog, da se spodnje pravilo kodiranja zapisovalnika ujema z vedenjem Excela
Zaščitite list, a pustite razvrščanje in filter odprta
Tukaj je pogost primer od začetka do konca: zaščitite dokončano poročilo, da postavitve ni mogoče preoblikovati, bralcu pa pustite razvrščanje in filtriranje. Upoštevajte, da sta Protect in možnosti neodvisna. Protect preklopi list v zaščiteno stanje in shrani neobvezni hash gesla; množice možnosti se ne dotakne. AllowOption prilagodite ločeno, preklopi pa začnejo veljati, ko je list zaščiten in shranjen
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;
Iz tega odseka velja prebrati dve stvari. Vrstici Sort in AutoFilter sta zapisani izrecno, čeprav je pri obeh privzeta vrednost True; to je dokumentacija za naslednjega vzdrževalca, ne funkcionalna zahteva. Ker so privzete vrednosti permisivne, izhodno datoteko dejansko spremenijo samo vrstice, ki možnost nastavijo na False. To ni naključje tega API-ja, temveč neposreden odsev žičnega formata OOXML, kar obravnava naslednji razdelek
Pravilo kodiranja: izpuščeno pomeni dovoljeno, attr=0 pomeni prepovedano
To je edino res protiintuitivno dejstvo v celotni funkciji in prav tu se ročno napisani <sheetProtection> običajno zmoti. V OOXML je vsak atribut za posamezno dejanje zastavica prepovej, njegova odsotnost pa pomeni dovoljenje. Če atribut manjka, je dejanje dovoljeno. Če je atribut zapisan kot "0", je dejanje med zaščito lista prepovedano. V pravilno oblikovani datoteki ni formatCells="1", ki bi pomenil "oblikovanje je dovoljeno"; atribut preprosto izpustite. (Privzeta vrednost odsotnega atributa je OOXML boolean default true, ti atributi pa so poimenovani tako, da true pomeni, da je ustrezno urejanje dovoljeno.)
Zapisovalnik HotXLS to natančno zrcali. Izpiše sheet="1", da vklopi zaščito, nato pregleda množico možnosti in zapiše attr="0" samo za tiste možnosti, ki ste jih nastavili na False. Dovoljena dejanja v izhod ne prispevajo ničesar. Zato se delovni zvezek iz prejšnjega razdelka serializira približno tako, da nosi samo prepovedana dejanja in hash gesla:
// 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.
Če prihajate iz starega trdo kodiranega niza in ste pričakovali, da bodo vsi atributi izpisani dobesedno, je to videti redko, skoraj napačno. Pa ni. Datoteka, ki bi navajala sort="1" in autoFilter="1", bi za skladnega bralca pomenila isto, toda Excel sam zapisuje minimalno obliko samo s prepovedmi, zato ujemanje z njim ohranja razlike majhne in round-trip dolgočasen na dober način. Atributa objects in scenarios sledita povsem istemu pravilu: privzeto sta dovoljena, zato se pojavita kot "0" samo takrat, ko ju prepoveste, kar je obratno od starega objects="1" scenarios="1", ki se je zapisoval brezpogojno
Branje zaščite nazaj: zvestoba round-tripu
Model dovoljenj, ki ga znate zapisati, ne pa tudi prebrati, je enosmerna ulica. Običajen simptom je cikel naloži-uredi-shrani, ki tiho razširi dovoljenja. HotXLS to zapre. Ko ParseWorksheetXml naleti na element <sheetProtection>, list označi kot zaščiten, zajame hash gesla, če je prisoten, in nato vsak atribut za posamezno dejanje dekodira nazaj v AllowOption z isto konvencijo v obratni smeri: prisoten atribut z vrednostjo "0" prepove dejanje; odsoten atribut pusti možnost pri njenem dovoljenem privzetem stanju
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;
Naložite datoteko, ki jo je ustvaril zapisovalnik, in dobite Sort in AutoFilter nazaj kot True, FormatCells pa kot False - točno tisto množico, ki ste jo shranili. Prav ta simetrija je bistvo: če v zaščitenem listu z delno dovoljenimi dejanji uredite eno celico in ga znova shranite, preostalih štirinajst dovoljenj, ki se jih niste dotaknili, preživi namesto da bi se sesulo nazaj na stari privzeti model vse ali nič
Praktične opombe in omejitve
Preden to povežete s cevovodom poročil, je koristno vedeti nekaj stvari:
- Geslo je po zasnovi šibko. Zaščita delovnega lista XLSX shranjuje 16-bitni podedovani hash (isti, ki ga Excel uporablja že desetletja), tukaj ohranjen zaradi interoperabilnosti. Odvrne nenamerne popravke, ne pa napadalca. Ne obravnavajte ga kot varovalo skrivnosti. Za resnično zaščito šifrirajte delovni zvezek
- Nastavljanje možnosti pred zaščito je v redu.
AllowOptionlahko dodelite ne glede na to, ali je list trenutno zaščiten ali ne; preklopi samo opisujejo, kaj bo zaščita dovolila, ko bo v veljaviProtect.UnProtectpočisti zaščiteno stanje in hash, a vašo množico možnosti pusti na mestu za naslednjič - Semantika zaklenjenih celic še vedno velja. Zaščita blokira urejanje samo tistih celic, pri katerih je nastavljen atribut
Locked(privzeta nastavitev delovnega zvezka). Če želite območje za vnos pustiti urejano, je to naloga sloga celice, ne možnosti zaščite; plasti se združita enako kot v Excelu - To je pogon XLSX. Model možnosti zrcali starejše lastnosti
Allow*v pogonu XLS, vendar enum in imena lastnosti tukaj (xlsxSpo*,AllowOption) pripadajoTXLSXWorksheetvlxHandleX. Če na istih listih upravljate tudi postavitev za tisk, sprehod skozi zaščito in nastavitev strani pokaže, kako te nastavitve stojijo ob območjih tiskanja in glavah strani, preverjanje veljavnosti podatkov, AutoFilter in tabele pa se naravno ujame s tem, daxlsxSpoAutoFilterpustite odprt na zaklenjenem poročilu
Model zaščite z natančnimi dovoljenji in preostali pogon za branje in zapisovanje XLSX sta del komponente HotXLS za Delphi in C++Builder; stran izdelka vsebuje celoten API delovnega lista skupaj s popolnim sklicem možnosti zaščite