Você entrega uma pasta de trabalho pronta a um colega e pede que ele filtre o conteúdo, não que o reescreva. Então você protege a folha de cálculo. Nas versões antigas do HotXLS, esse gesto gravava uma única coisa no ficheiro: <sheetProtection sheet="1" objects="1" scenarios="1"/>, fixo, sempre. A folha de cálculo era bloqueada, o hash da palavra-passe era anexado e o utilizador não podia fazer mais nada, nem mesmo a ordenação e o filtro que você realmente queria deixar abertos. A caixa de diálogo "Proteger Folha de cálculo" do próprio Excel tem quinze caixas de seleção exatamente por esse motivo, e o mecanismo não conseguia expressar nenhuma delas. É essa lacuna que o modelo de proteção da v2.91.0 fecha
HotXLS é um componente nativo VCL de folhas de cálculo para Delphi e C++Builder que lê e grava XLS e XLSX sem precisar do Excel instalado. Este artigo trata do lado XLSX da proteção de folhas de cálculo: o novo enum TXLSXSheetProtectionOption, a propriedade AllowOption que alterna cada permissão e a única regra de codificação OOXML que sempre pega quem escreve um elemento <sheetProtection> à mão
O que a proteção de folha de cálculo realmente guarda
Primeiro, o limite, porque ele determina o quanto você deve confiar em tudo isso. A proteção de folha de cálculo no formato de folha de cálculo OOXML (ECMA-376) é uma política de interação, não criptografia. Ela diz a um aplicação compatível quais edições devem ser recusadas enquanto a folha de cálculo está protegida. Os valores das células continuam em xl/worksheets/sheetN.xml em texto puro; basta abrir o .xlsx e eles estão lá. A palavra-passe opcional é armazenada como um hash antigo e curto, não como uma chave que embaralha os dados. Qualquer pessoa que renomeie o ficheiro, abra a parte e remova a linha <sheetProtection> lê e edita tudo
Então a proteção responde "impedir que meu colega apague uma fórmula por engano", não "manter esses dados secretos de alguém determinado". São problemas diferentes, com ferramentas diferentes. Se você necessita de confidencialidade, quer a criptografia no nível da pasta de trabalho coberta em saída XLSX protegida por AES, que de fato cifra o pacote. Proteção de folha de cálculo e criptografia de pasta de trabalho se combinam bem, mas só a segunda é um cadeado. Mantenha essa distinção clara e o resto da página vira apenas encanamento
As quinze opções e a propriedade AllowOption
Cada folha de cálculo agora carrega um conjunto de valores TXLSXSheetProtectionOption que descrevem o que o utilizador ainda pode fazer enquanto a folha de cálculo está protegida. Os membros se mapeiam um a um para os atributos OOXML e para as caixas de seleção da caixa de diálogo do Excel:
xlsxSpoEditObjects,xlsxSpoEditScenarios- editar objetos de desenho e cenários hipotéticosxlsxSpoFormatCells,xlsxSpoFormatColumns,xlsxSpoFormatRows- reformatar células, colunas e linhasxlsxSpoInsertColumns,xlsxSpoInsertRows,xlsxSpoInsertHyperlinks- inserir colunas, linhas e linksxlsxSpoDeleteColumns,xlsxSpoDeleteRows- excluir colunas e linhasxlsxSpoSelectLockedCells,xlsxSpoSelectUnlockedCells- mover a seleção para células bloqueadas ou desbloqueadasxlsxSpoSort,xlsxSpoAutoFilter,xlsxSpoPivotTables- ordenar intervalos, usar menus do AutoFilter e trabalhar com PivotTables
Você lê e grava bits individuais pela propriedade indexada AllowOption em TXLSXWorksheet. AllowOption[Opt] = True significa que a ação é permitida; definir False a proíbe. O conjunto inteiro também pode ser acessado de uma vez por SheetProtectionOptions, um TXLSXSheetProtectionOptions (um simples set of Pascal), então você pode salvá-lo, restaurá-lo ou substituí-lo por completo
O predefinido importa e é intencional: uma worksheet recém-criada inicia com todas as opções permitidas. O construtor preenche SheetProtectionOptions com o intervalo inteiro, [Low(TXLSXSheetProtectionOption)..High(TXLSXSheetProtectionOption)]. Você restringe a partir daí excluindo as ações que quer proibir, em vez de montar um conjunto de permissões do zero. É essa escolha que faz a regra de codificação do escritor, abaixo, coincidir com o comportamento do Excel
Proteger uma folha de cálculo e deixar ordenação e filtro abertos
Este é o caso comum de ponta a ponta: proteger um relatório pronto para que o layout não seja remexido, mas deixar o leitor ordená-lo e filtrá-lo. Observe que Protect e as opções são independentes. Protect coloca a folha de cálculo no estado protegido e armazena o hash opcional da palavra-passe; ele não mexe no conjunto de opções. Você ajusta AllowOption separadamente, e as alternâncias entram em vigor quando a folha de cálculo é protegida e guarda
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;
Há duas coisas a tirar desse trecho. As linhas Sort e AutoFilter são escritas explicitamente mesmo que ambas tenham predefinido True; isso é documentação para quem vier depois, não requisito funcional. E, como os padrões são permissivos, as únicas linhas que alteram o ficheiro de saída são as que colocam uma opção como False. Isso não é um acidente desta API, é o formato OOXML aparecendo na superfície, que é o próximo tópico
A regra de codificação: omitir significa permitir, attr=0 significa proibir
Este é o único fato contraintuitivo de todo o recurso, e é onde o <sheetProtection> escrito à mão costuma errar. Em OOXML, cada atributo por ação é uma flag de proibição, e sua ausência significa permissão. Um atributo ausente quer dizer que a ação é permitida. Um atributo escrito como "0" quer dizer que a ação é proibida enquanto a folha de cálculo estiver protegida. Não existe formatCells="1" em um ficheiro bem formado para significar "a formatação é permitida"; basta omitir o atributo. (O predefinido de um atributo ausente é o booleano true do OOXML, e esses atributos são nomeados de maneira que "true" signifique que a edição correspondente é permitida.)
O escritor do HotXLS espelha isso exatamente. Ele emite sheet="1" para ativar a proteção e então percorre o conjunto de opções escrevendo attr="0" apenas para as opções que você definiu como False. As ações permitidas não geram saída. Então a pasta de trabalho da secção anterior se serializa para algo assim, levando apenas as ações proibidas e o hash da palavra-passe:
// 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.
Se você veio da antiga string fixa e esperava ver cada atributo escrito por extenso, isso parece esparso, quase errado. Mas está certo. Um ficheiro que listasse sort="1" e autoFilter="1" significaria a mesma coisa para um leitor compatível, mas o próprio Excel grava a forma mínima, só com proibições, e imitar isso mantém os diffs pequenos e as idas e voltas sem drama. Os atributos objects e scenarios seguem a mesma regra: eles são permitidos por predefinição, então só aparecem como "0" quando você os proíbe, o oposto do antigo objects="1" scenarios="1" que era emitido sem condição
Ler a proteção de volta: fidelidade ida e volta
Um modelo de permissões que você pode gravar mas não ler é uma via de mão única, e o sintoma normal é um ciclo carregar-editar-guardar que alarga permissões em silêncio. O HotXLS resolve isso. Quando ParseWorksheetXml encontra um elemento <sheetProtection>, ele marca a folha de cálculo como protegida, captura o hash da palavra-passe se houver e então decodifica cada atributo por ação de volta para AllowOption usando a mesma convenção ao contrário: um atributo presente e igual a "0" proíbe a ação; um atributo ausente deixa a opção no predefinido permitido
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;
Carregue o ficheiro produzido pelo escritor e você recebe Sort e AutoFilter de volta como True, FormatCells como False - o conjunto que você salvou, intacto. Essa simetria é o objetivo inteiro: edite uma célula em uma folha de cálculo protegida com permissões parciais e salve de novo, e as catorze permissões que você não tocou sobrevivem em vez de colapsarem para o antigo predefinido tudo ou nada
Notas práticas e limites
Algumas coisas valem saber antes de encaixar isso em um pipeline de relatórios:
- A palavra-passe é fraca por design. A proteção de folha de cálculo XLSX armazena um hash legado de 16 bits, o mesmo que o Excel usa há décadas, mantido aqui por interoperabilidade. Ela desencoraja edições acidentais, mas não resiste a um atacante. Não a trate como guardiã de segredo. Para proteção real, criptografe a pasta de trabalho
- Definir opções antes de proteger é tranquilo.
AllowOptionpode ser atribuído com a folha de cálculo protegida ou não; as alternâncias apenas descrevem o que a proteção permitirá quandoProtectentrar em vigor.UnProtectlimpa o estado protegido e o hash, mas deixa o conjunto de opções em vigor para a próxima vez - A semântica de célula bloqueada continua valendo. A proteção só bloqueia edições em células cujo atributo
Lockedestá definido, o predefinido da pasta de trabalho. Deixar uma área de entrada editável é tarefa do estilo da célula, não de uma opção de proteção; as duas camadas se combinam do mesmo jeito que no Excel - Este é o mecanismo XLSX. O modelo de opções espelha as antigas propriedades
Allow*do mecanismo XLS, mas o enum e os nomes de propriedade aqui (xlsxSpo*,AllowOption) pertencem aTXLSXWorksheetemlxHandleX. Se você também controla o layout de impressão nas mesmas folhas de cálculo, o guia de proteção e configuração de página mostra como essas definições convivem com áreas de impressão e cabeçalhos, e validação de dados, AutoFilter e tabelas combina naturalmente com deixarxlsxSpoAutoFilteraberto em um relatório bloqueado
O modelo de proteção granular e o restante do mecanismo de leitura e gravação XLSX fazem parte do HotXLS Component para Delphi e C++Builder; a página do produto traz a API completa da worksheet, inclusive a referência integral das opções de proteção