// Hook: AfterPacketGeneration // Apply sheet-level protection across every visible worksheet. // // The password comes from the "SheetProtectionPassword" job parameter. Filter, // sort, and pivot interactions remain enabled so finance users can still slice // the data; structural edits and formula tampering are blocked. if (Workbook == null) { AddWarning($"No workbook available for '{OutputName}'; skipping protection."); return; } if (!Parameters.TryGetValue("SheetProtectionPassword", out var password) || string.IsNullOrEmpty(password)) { AddWarning("Parameter 'SheetProtectionPassword' missing; sheets left unprotected."); return; } int protectedCount = 0; foreach (Worksheet sheet in Workbook.Worksheets) { if (!sheet.IsVisible) continue; sheet.Protect(ProtectionType.All, password, null); sheet.Protection.AllowFiltering = true; sheet.Protection.AllowSorting = true; sheet.Protection.AllowUsingPivotTable = true; sheet.Protection.AllowSelectingLockedCell = true; sheet.Protection.AllowSelectingUnlockedCell = true; protectedCount++; } Workbook.Settings.WriteProtection.Password = password; Logger.LogInformation($"Protected {protectedCount} sheet(s) in '{OutputName}'.");