Átad egy elkészült munkafüzetet egy kollégájának, és arra kéri, hogy szűrje azt, ne pedig újraírja. Ezért védi a munkalapot. A régebbi HotXLS verziókban ez a lépés mindig egyetlen dolgot írt a fájlba: <sheetProtection sheet="1" objects="1" scenarios="1"/>, mereven kódolva. A munkalap lezárult, a jelszó-hash csatolásra került, és a felhasználó egyáltalán semmit sem tehetett, még a rendezést és szűrést sem, amit valójában nyitva akart hagyni. Az Excel saját „Munkalap védelme” párbeszédpanele pontosan ezért tartalmaz tizenöt jelölőnégyzetet, és a motor ezek egyikét sem tudta kifejezni. Ezt a hiányt zárja be a v2.91.0 védelmi modellje
A HotXLS egy natív VCL táblázatkezelő komponens Delphihez és C++Builderhez, amely Excel telepítése nélkül olvassa és írja az XLS és XLSX fájlokat. Ez a cikk a munkalap-védelem XLSX oldaláról szól: az új TXLSXSheetProtectionOption felsorolásról (enum), az egyes engedélyeket kapcsoló AllowOption tulajdonságról, valamint arról az egy OOXML kódolási szabályról, amely mindenkit megzavar, aki kézzel ír egy <sheetProtection> elemet
Mit véd valójában a munkalap-védelem
Először is tisztázzuk a határokat, mert ez dönti el, mennyire bízhat ebben a megoldásban. A munkalap-védelem az OOXML táblázatkezelő formátumban (ECMA-376) egy interakciós házirend, nem pedig titkosítás. Megmondja a szabályos alkalmazásnak, hogy mely szerkesztéseket utasítsa el, miközben a munkalap védett. A cellaértékek továbbra is egyszerű szövegként ülnek az xl/worksheets/sheetN.xml fájlban; bontsa ki a .xlsx fájlt, és ott vannak. Az opcionális jelszó rövid, örökölt hash-ként tárolódik, nem pedig olyan kulcsként, amely bármit is összekeverne. Bárki, aki átnevezi a fájlt, megnyitja a részt, és eltávolítja a <sheetProtection> sort, mindent elolvashat és szerkeszthet
Így a védelem arra válaszol, hogyan „akadályozzam meg, hogy a munkatársam véletlenül elrontson egy képletet”, nem pedig arra, hogyan „tartsam titokban ezeket az adatokat egy motivált személlyel szemben”. Ezek különböző problémák különböző eszközökkel. Ha titkosságra van szüksége, akkor a munkafüzet-szintű titkosítást szeretné, amelyről a AES-védett XLSX kimenet című cikk szól, és amely ténylegesen titkosítja a csomagot. A munkalap-védelem és a munkafüzet-titkosítás tisztán összekapcsolódik, de csak a második jelent valódi zárat. Tartsa ezt a határvonalat tisztán, és a lap többi része már csak technikai részlet
A tizenöt lehetőség és az AllowOption tulajdonság
Minden munkalap mostantól a TXLSXSheetProtectionOption értékek készletét hordozza, leírva, hogy a felhasználó mit tehet még, miközben a munkalap védett. A tagok egy az egyben leképeződnek az OOXML attribútumokra és az Excel párbeszédpanel jelölőnégyzeteire:
xlsxSpoEditObjects,xlsxSpoEditScenarios— rajzobjektumok és „mi lenne ha” forgatókönyvek szerkesztésexlsxSpoFormatCells,xlsxSpoFormatColumns,xlsxSpoFormatRows— cellák, oszlopok, sorok újraformázásaxlsxSpoInsertColumns,xlsxSpoInsertRows,xlsxSpoInsertHyperlinks— oszlopok, sorok, hivatkozások beszúrásaxlsxSpoDeleteColumns,xlsxSpoDeleteRows— oszlopok, sorok törlésexlsxSpoSelectLockedCells,xlsxSpoSelectUnlockedCells— kijelölés mozgatása zárolt vagy feloldott cellákraxlsxSpoSort,xlsxSpoAutoFilter,xlsxSpoPivotTables— tartományok rendezése, AutoSzűrő legördülő menük használata, PivotTáblák kezelése
Az egyes biteket a TXLSXWorksheet indexelt AllowOption tulajdonságán keresztül olvashatja és írhatja. Az AllowOption[Opt] = True azt jelenti, hogy a művelet engedélyezett; False-ra állítása megtiltja azt. A teljes készlet egyszerre is elérhető a SheetProtectionOptions tulajdonságon keresztül, amely egy TXLSXSheetProtectionOptions (egy egyszerű Pascal set of), így elmentheti, visszaállíthatja vagy teljes egészében kicserélheti azt
Az alapértelmezés számít és szándékos: a frissen létrehozott munkalap minden engedélyezett opcióval indul. A konstruktor a SheetProtectionOptions tulajdonságot a teljes tartománnyal tölti fel: [Low(TXLSXSheetProtectionOption)..High(TXLSXSheetProtectionOption)]. Innen szűkítheti a kört a megtiltani kívánt műveletek kizárásával, ahelyett, hogy a semmiből építene fel egy engedélykészletet. Ez a választás teszi lehetővé, hogy az író alábbi kódolási szabálya összhangban legyen az Excel viselkedésével
Munkalap védelme, de a rendezés és szűrés nyitva hagyása
Itt a gyakori eset elejétől a végéig: védjen meg egy elkészült jelentést, hogy az elrendezés ne legyen módosítható, de engedje meg az olvasónak a rendezést és a szűrést. Vegye figyelembe, hogy a Protect és az opciók függetlenek egymástól. A Protect védett állapotba helyezi a lapot és eltárolja az opcionális jelszó-hasht; nem nyúl az opciókészlethez. Az AllowOption tulajdonságot külön állíthatja be, és a kapcsolók a munkalap védelme és mentése után lépnek életbe
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;
// Védelem jelszóval. Ez csak a védett állapotot + hasht állítja be;
// az opciókészlet az összes engedélyezett alapértelmezésen marad.
sh.Protect('HotXLS-2026');
// Szűkítés: rendezés + AutoSzűrő megtartása, módosítás és formázás megtiltása.
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;
Két dolog olvasható le ebből a kódrészletből. A Sort és AutoFilter sorok kifejezetten le vannak írva, bár mindkettő alapértelmezetten True; ez a dokumentáció a következő karbantartónak szól, nem pedig funkcionális követelmény. És mivel az alapértelmezések megengedőek, az egyetlen sorok, amelyek megváltoztatják a kimeneti fájlt, azok, amelyek egy opciót False értékre állítanak. Ez nem az API véletlene, hanem az OOXML átviteli formátumának megjelenése, amiről a következő szakasz szól
A kódolási szabály: az elhagyás engedélyezést jelent, az attr=0 megtiltást jelent
Ez az egyetlen ellenértelmű tény a teljes funkcióban, és itt szokott a kézzel írt <sheetProtection> elromlani. Az OOXML-ben minden műveletenkénti attribútum egy tiltó jelző, és annak hiánya engedélyezést jelent. A hiányzó attribútum azt jelenti, hogy a művelet engedélyezett. A "0" értékként leírt attribútum azt jelenti, hogy a művelet tilos, miközben a munkalap védett. Egy jól formázott fájlban nincs olyan, hogy formatCells="1", ami azt jelentené, hogy „a formázás engedélyezett”; egyszerűen el kell hagyni az attribútumot. (A hiányzó attribútum alapértelmezett értéke az OOXML logikai true alapértelmezése, és ezek az attribútumok úgy vannak elnevezve, hogy a „true” a megfelelő szerkesztés engedélyezését jelenti)
A HotXLS író pontosan ezt tükrözi. Kibocsátja a sheet="1" értéket a védelem bekapcsolásához, majd végigjárja az opciókészletet, és csak a False értékre állított opciókhoz ír attr="0"-t. Az engedélyezett műveletek semmivel sem járulnak hozzá a kimenethez. Így az előző szakaszban bemutatott munkafüzet valami hasonlóra szerializálódik, csak a tiltott műveleteket és a jelszó-hasht hordozva:
// Elvi kimenet a fenti részlethez (az attribútumok a rövidség kedvéért elhagyva):
// <sheetProtection sheet="1"
// formatCells="0" formatColumns="0" formatRows="0"
// insertRows="0" deleteRows="0"
// password="...4-hex..."/>
// Figyelje meg, mi NINCS ott: nincs sort, nincs autoFilter, no selectLockedCells.
// Hiányuk pontosan az, ami jelzi az Excelnek, hogy ezek a műveletek engedélyezettek maradnak.
Ha a régi mereven kódolt karakterláncból jött, és arra számított, hogy minden attribútumot kiírva lát, ez ritkásnak, szinte hibásnak tűnhet. Ez helyes. Egy olyan fájl, amely a sort="1" és autoFilter="1" értékeket listázná, ugyanazt jelentené a szabályos megjelenítőnek, de az Excel maga is a minimális tiltó formát írja, és ennek követése kis méretű diffeket és unalmas oda-vissza utakat tesz lehetővé. Az objects és scenarios attribútumok ugyanezt a szabályt követik: alapértelmezetten engedélyezettek, így csak "0"-ként jelennek meg, ha megtiltja őket, ami az unconditionally kibocsátott régi objects="1" scenarios="1" fordítottja
A védelem visszaolvasása: oda-vissza hűség
Egy olyan engedélyezési modell, amelyet csak írni lehet, de olvasni nem, egyirányú ajtó, és a szokásos tünet egy olyan betöltés-szerkesztés-mentés ciklus, amely csendben kibővíti az engedélyeket. A HotXLS ezt bezárja. Amikor a ParseWorksheetXml találkozik egy <sheetProtection> elemmel, védetté állítja a lapot, rögzíti a jelszó-hasht, ha jelen van, majd visszafejti az egyes műveletenkénti attribútumokat a AllowOption-ba, ugyanazt a konvenciót alkalmazva fordítva: a jelen lévő és "0" értékű attribútum megtiltja a műveletet; a hiányzó attribútum pedig az engedélyezett alapértelmezésen hagyja az opciót
var
wb: TXLSXWorkbook;
sh: TXLSXWorksheet;
begin
wb := TXLSXWorkbook.Create;
try
wb.LoadFromFile('protection.xlsx');
sh := wb.Sheets[1]; // Az XLSX munkalapok 1-alapúak
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;
Töltse be az író által létrehozott fájlt, és a Sort és AutoFilter értékeket True, a FormatCells értéket pedig False-ként kapja vissza — a mentett készlet sértetlen marad. Ez a szimmetria a lényeg: szerkesszen egyetlen cellát egy védett, részben engedélyezett munkalapon, majd mentse újra, és az a tizennégy engedély, amelyhez nem nyúlt hozzá, fennmarad ahelyett, hogy visszaesne a régi mindent-vagy-semmit alapértelmezésre
Praktikus megjegyzések és korlátok
Néhány dolog, amit érdemes tudni, mielőtt ezt beépítené a jelentéskészítő folyamatba:
- A jelszó tervezéséből adódóan gyenge. Az XLSX munkalap-védelem egy 16 bites örökölt hasht tárol (ugyanazt, amelyet az Excel évtizedek óta használ), amely az interoperabilitás érdekében maradt meg. Megakadályozza a véletlen szerkesztéseket; nem áll ellen a támadónak. Ne kezelje titoktartóként. Valódi védelemhez titkosítsa a munkafüzetet
- Az opciók beállítása a védelem előtt is lehetséges. A
AllowOptionérték hozzárendelhető függetlenül attól, hogy a lap jelenleg védett-e vagy sem; a kapcsolók egyszerűen azt írják le, mit fog engedélyezni a védelem, amint aProtectéletbe lép. AzUnProtecttörli a védett állapotot és a hasht, de az opciókészletet a helyén hagyja a következő alkalomra - A zárolt cella szemantika továbbra is érvényes. A védelem csak azokat a cellákat blokkolja, amelyeknek a
Lockedattribútuma be van állítva (ez a munkafüzet alapértelmezése). Egy beviteli terület szerkeszthetővé tétele a cellastílus feladata, nem pedig védelmi opció; a kai réteg ugyanúgy kombinálódik, mint az Excelben - Ez az XLSX motor. Az opciómodell tükrözi az XLS motor régebbi
Allow*tulajdonságait, de az enum és tulajdonságnevek itt (xlsxSpo*,AllowOption) aTXLSXWorksheet-hez tartoznak azlxHandleX-ben. Ha ugyanazokon a lapokon a nyomtatási elrendezést is vezérli, a védelem és oldalbeállítás útmutató bemutatja, hogyan helyezkednek el ezek a beállítások a nyomtatási területek és fejlécek mellett, míg a adatérvényesítés, AutoSzűrő és táblázatok természetes módon párosul axlsxSpoAutoFilterengedélyezve hagyásával egy zárolt jelentésen
A részletes védelmi modell és az XLSX olvasó/író motor többi része a HotXLS Component csomagban érkezik Delphihez és C++Builderhez; a termékoldal tartalmazza a teljes munkalap API-t, beleértve a teljes védelmi opció referenciát is