Trois groupes de réglages de feuille de calcul n'ont rien à voir avec les valeurs des cellules et tout à voir avec le comportement du fichier une fois qu'il a quitté votre code. La protection de feuille décide quelles cellules un utilisateur pourra modifier après que vous lui aurez remis le classeur. La mise en page fixe l'orientation, le format de papier et les marges. Les réglages d'impression (lignes de titre répétées, mise à l'échelle et sauts de page manuels) commandent la façon dont une grille de longueur quelconque se pose sur le papier. Aucun des trois n'apparaît quand vous inspectez les données dans une visionneuse, et les trois cassent en silence sur le terrain quand ils sont faux. HotXLS, bibliothèque tableur native pour Delphi et C++Builder, expose la surface complète pour .xls et .xlsx, ce qui signifie qu'elle reproduit aussi chaque règle Excel contre-intuitive cuite dans cette surface
La première de ces règles fait trébucher presque tout le monde la première fois que l'on protège une feuille générée. Appelez Protect et soudain plus personne ne peut taper dans aucune cellule, y compris les colonnes de saisie autour desquelles vous avez bâti le classeur. Rien dans votre code n'a touché ces colonnes, et c'est exactement pour cela que cela se produit
Chaque cellule naît verrouillée
ECMA-376 définit locked comme une partie de l'enregistrement de mise en forme d'une cellule, non comme une propriété de la protection elle-même, et sa valeur par défaut est vraie. La protection de feuille n'est que l'interrupteur qui rend l'indicateur applicable. Toute la grille porte donc un indicateur de verrou dès son existence, en sommeil, et l'appel à Protect les active tous d'un coup. Le remède consiste à fixer l'ordre délibérément : construisez la disposition, déverrouillez explicitement les plages que les utilisateurs doivent modifier, et protégez en dernier
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Timesheet');
// ... ligne d'en-tête, colonne des noms et formules de taux écrites ici ...
Sheet.Range['B2:B50'].SetLocked(False); // le personnel saisit ses heures ici
Sheet.Range['F2:F50'].SetFormulaHidden(True); // garder privé le calcul du taux
Sheet.Protect('review-2026'); // les indicateurs de verrou mordent maintenant
Book.SaveAs('timesheet.xlsx');
finally
Book.Free;
end;
SetFormulaHidden fait quelque chose de distinct et facile à manquer : tant que la protection est active, la cellule affiche encore sa valeur calculée, mais la barre de formule ne montre rien. Cela compte quand une formule incorpore des taux de facturation, des marges ou des pondérations de notation que vous préféreriez ne pas remettre à chaque destinataire qui clique sur un total. Sur la façade XLS, la même intention s'exprime plage par plage via IXLSRange.Locked et FormulaHidden. La feuille de calcul y porte aussi quinze indicateurs Allow* (AllowSort, AllowAutoFilter, AllowFormatCells et les autres), si bien qu'une feuille protégée peut encore être triée et filtrée au lieu d'être figée en pièce scellée
Ce que le mot de passe de protection protège réellement
Les deux formats rangent le mot de passe de protection de feuille et de classeur sous forme d'une empreinte héritée de 4 chiffres hexadécimaux. Seize bits signifient que d'innombrables chaînes entrent en collision avec n'importe quel mot de passe donné, et les outils de suppression sont à une recherche de distance. Traitez la protection comme une ceinture de sécurité contre les modifications accidentelles, non comme un contrôle d'accès. C'est le bon outil pour empêcher des relecteurs d'écraser la colonne des formules et le mauvais outil pour tout ce qui met en jeu le mot confidentiel
Un niveau au-dessus, ProtectWorkbook sur la façade XLSX verrouille la structure du classeur, ce qui empêche d'ajouter, de renommer, de supprimer ou de réordonner des feuilles. Activez-le dès que la liste des feuilles est elle-même un contrat avec un analyseur en aval qui indexe les feuilles par nom ou par position. Une feuille renommée casse l'import de l'autre côté tout aussi sûrement qu'une colonne supprimée. La façade XLS reflète cette superposition avec TXLSWorkbook.Protect au niveau du classeur et des appels Protect par feuille, plus une propriété isProtected pour le code qui doit inspecter un fichier hérité avant de modifier quoi que ce soit
Quand l'exigence est une vraie confidentialité, le mécanisme change entièrement. SaveAsEncrypted produit un paquet chiffré en AES sous le schéma de chiffrement standard d'ECMA-376, traité en profondeur dans le guide de la sortie XLSX protégée par AES, et la façade XLS héritée écrit et lit des fichiers .xls chiffrés en RC4 via EncryptionPassword et la surcharge à mot de passe de Open. La différence n'a rien d'académique. Une feuille protégée voyage en clair, si bien que n'importe quel outil zip peut lire ses valeurs de cellules, tandis qu'un paquet chiffré reste illisible sans le mot de passe. Une ligne d'audit qui dit « le fichier de paie doit être protégé » signifie presque toujours chiffrement, quel que soit le vocabulaire employé
La mise en page fait partie du contrat du document
Le comportement à l'impression est invisible à l'écran, ce qui explique qu'il parte si souvent cassé. Dès qu'un client imprime le classeur, ou l'exporte en PDF pour un auditeur, les marges, la mise à l'échelle et les titres répétés deviennent des exigences fonctionnelles que personne n'a testées. Sur la façade XLSX, ces réglages pendent directement de la feuille de calcul :
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'; // référence nue : pas de nom de feuille ici
Sheet.PrintTitleRows := '$1:$1'; // la ligne d'en-tête se répète sur chaque page
Sheet.FitToWidth := 1;
Sheet.FitToHeight := 0; // grandir vers le bas à mesure que les données grandissent
Sheet.PrintGridlines := False;
Deux de ces lignes cachent des pièges. Les chaînes d'en-tête et de pied de page utilisent les codes de mise en forme d'Excel : &P pour la page courante, &N pour le nombre total, avec &L, &C et &R pour adresser explicitement les trois sections. L'autre piège est PrintArea, qui prend une référence de cellule nue à dessein. HotXLS la range non qualifiée et préfixe le nom de feuille au moment d'écrire le fichier, si bien que passer vous-même 'Timesheet!$A$1:$F$60' produit une référence doublement qualifiée et mal formée. La même prudence vaut une couche plus bas : les zones d'impression et les titres d'impression sont persistés comme les noms définis intégrés _xlnm.Print_Area et _xlnm.Print_Titles, alors n'ajoutez jamais d'entrées _xlnm.* à la main par DefinedNames, sinon les deux mécanismes se disputeront le même emplacement
Une mise à l'échelle qui survit aux volumes de production
La combinaison de FitToWidth := 1 avec FitToHeight := 0 se lit comme « toujours faire tenir les colonnes sur la largeur d'une page, puis prendre autant de pages en hauteur que les données en demandent », et c'est la valeur par défaut correcte pour tout rapport dont le nombre de lignes varie. Le piège consiste à régler un pourcentage fixe ou un couple d'ajustement à la page sur un fichier de test de trente lignes : donnez aux mêmes réglages six cents lignes de production et la sortie explose en dizaines de pages tronquées ou rétrécit sous le seuil de lisibilité. Mettez la largeur à l'échelle, laissez la longueur grandir, et répétez la ligne d'en-tête par PrintTitleRows afin que la page dix-sept reste lisible à elle seule
Les sauts manuels suivent la même discipline de régénération que tout le reste dans un classeur généré. AddRowBreak(BeforeRow) commence une nouvelle page avant une limite de section, mais quand le générateur se relance et que les lignes se décalent, un saut périmé atterrit au milieu d'un tableau. Appelez d'abord ClearAllPageBreaks, puis rajoutez les sauts calculés à partir des compteurs de lignes du générateur lui-même au lieu de rapiécer d'anciennes positions. Sur la façade XLS, les commandes équivalentes vivent sur Sheet.PageSetup (orientation, format de papier, marges, chaînes d'en-tête et de pied de page, ajustement au nombre de pages), RepeatRows et RepeatColumns couvrant les titres d'impression
Contrôler le résultat avant qu'un client le fasse
Les bogues de protection et d'impression partagent une propriété : ils sont triviaux à vérifier à la main et ne sont presque jamais vérifiés. Ouvrez le fichier généré dans Excel et passez-y quatre-vingt-dix secondes. Tapez dans une cellule de saisie et confirmez qu'elle accepte la frappe ; tapez dans une cellule verrouillée et confirmez que l'invite de protection apparaît ; vérifiez qu'une formule masquée laisse la barre de formule vide. Lancez ensuite l'aperçu avant impression sur un jeu de données de taille production, pas sur un échantillon de trente lignes, et relevez le nombre de pages, la ligne de titre répétée et la numérotation du pied de page. L'aperçu est l'étape qui se rembourse toute seule, car la géométrie d'impression dépend de réglages sans rendu à l'écran et, à défaut d'imprimante physique, c'est le seul endroit où une erreur de mise à l'échelle devienne jamais visible
Un dernier réglage complète la revue. FreezePane(ACol, ARow) garde le bloc d'en-tête en vue pendant qu'un relecteur fait défiler. C'est un comportement d'écran plutôt que d'impression, mais un relecteur juge tout le livrable d'un bloc. Et un classeur qui commence sa vie comme une mise en page entretenue par un concepteur obtient l'essentiel de tout cela gratuitement : le flux de génération de rapports par modèle garde la mise en page dans le modèle, où un humain l'a réglée face à une vraie imprimante, et laisse au code le soin de remplir les données et de réappliquer la protection une fois la disposition stabilisée
HotXLS est une bibliothèque tableur native en Object Pascal pour Delphi et C++Builder ; la référence complète de l'API de protection et de mise en page se trouve sur la page produit du HotXLS Delphi Component