Skip to content

Commit c34d94b

Browse files
Fixed worksheet protection handling; Added test
1 parent 99918f9 commit c34d94b

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

NanoXLSX/LowLevel/XlsxWriter.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,11 +1049,18 @@ private string CreateSheetProtectionString(Worksheet sheet)
10491049
{
10501050
actualLockingValues.Add(Worksheet.SheetProtectionValue.scenarios, 1);
10511051
}
1052-
if (!sheet.SheetProtectionValues.Contains(Worksheet.SheetProtectionValue.selectLockedCells))
1052+
bool allowSelectLocked = sheet.SheetProtectionValues.Contains(Worksheet.SheetProtectionValue.selectLockedCells);
1053+
bool allowSelectUnlocked = sheet.SheetProtectionValues.Contains(Worksheet.SheetProtectionValue.selectUnlockedCells);
1054+
if (allowSelectLocked && !allowSelectUnlocked)
1055+
{
1056+
// This shouldn't happen in Excel's UI, but handle it by allowing both
1057+
allowSelectUnlocked = true;
1058+
}
1059+
if (!allowSelectLocked)
10531060
{
10541061
actualLockingValues.Add(Worksheet.SheetProtectionValue.selectLockedCells, 1);
10551062
}
1056-
if (!sheet.SheetProtectionValues.Contains(Worksheet.SheetProtectionValue.selectUnlockedCells))
1063+
if (!allowSelectUnlocked)
10571064
{
10581065
actualLockingValues.Add(Worksheet.SheetProtectionValue.selectUnlockedCells, 1);
10591066
}
@@ -1375,24 +1382,17 @@ private string CreateStyleXfsString()
13751382
alignmentString = sb2.ToString();
13761383
}
13771384

1378-
if (style.CurrentCellXf.Hidden || !style.CurrentCellXf.Locked)
1385+
if (style.CurrentCellXf.Hidden && style.CurrentCellXf.Locked)
13791386
{
1380-
if (style.CurrentCellXf.Hidden && style.CurrentCellXf.Locked)
1381-
{
1382-
protectionString = "<protection locked=\"1\" hidden=\"1\"/>";
1383-
}
1384-
else if (style.CurrentCellXf.Hidden && !style.CurrentCellXf.Locked)
1385-
{
1386-
protectionString = "<protection hidden=\"1\" locked=\"0\"/>";
1387-
}
1388-
else if (!style.CurrentCellXf.Hidden && !style.CurrentCellXf.Locked)
1389-
{
1390-
protectionString = "<protection locked=\"0\"/>";
1391-
}
1392-
else
1393-
{
1394-
protectionString = "<protection locked=\"1\"/>";
1395-
}
1387+
protectionString = "<protection locked=\"1\" hidden=\"1\"/>";
1388+
}
1389+
else if (style.CurrentCellXf.Hidden && !style.CurrentCellXf.Locked)
1390+
{
1391+
protectionString = "<protection hidden=\"1\" locked=\"0\"/>";
1392+
}
1393+
else if (!style.CurrentCellXf.Hidden && !style.CurrentCellXf.Locked)
1394+
{
1395+
protectionString = "<protection locked=\"0\"/>";
13961396
}
13971397

13981398
sb.Append("<xf numFmtId=\"");

NanoXlsx Test/Worksheets/WorksheetWriteReadTest.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ public void SheetNameWriteReadTest()
498498
[InlineData(false, "", "", 0)]
499499
[InlineData(false, "autoFilter:0,sort:0", "", 0)]
500500
[InlineData(true, "", "objects:1,scenarios:1,selectLockedCells:1,selectUnlockedCells:1", 0)]
501+
[InlineData(true, "selectLockedCells:1,selectUnlockedCells:0", "objects:1,scenarios:1", 0)] // Special case: only locked cells selectable is not possible, therefore none
501502
[InlineData(true, "autoFilter:0", "autoFilter:0,objects:1,scenarios:1,selectLockedCells:1,selectUnlockedCells:1", 0)]
502503
[InlineData(true, "pivotTables:0", "pivotTables:0,objects:1,scenarios:1,selectLockedCells:1,selectUnlockedCells:1", 0)]
503504
[InlineData(true, "sort:0", "sort:0,objects:1,scenarios:1,selectLockedCells:1,selectUnlockedCells:1", 0)]
@@ -556,6 +557,32 @@ public void SheetProtectionWriteReadTest(bool useSheetProtection, string givenPr
556557
}
557558
}
558559

560+
[Fact(DisplayName = "Test of the 'SheetProtectionValues' when setting selectLockedCells alone (causes auto-fix)")]
561+
public void SheetProtectionWriteReadTest2()
562+
{
563+
int sheetIndex = 0;
564+
Workbook workbook = PrepareWorkbook(4, "test");
565+
for (int i = 0; i <= sheetIndex; i++)
566+
{
567+
if (sheetIndex == i)
568+
{
569+
workbook.SetCurrentWorksheet(i);
570+
workbook.CurrentWorksheet.AddAllowedActionOnSheetProtection(Worksheet.SheetProtectionValue.selectUnlockedCells);
571+
workbook.CurrentWorksheet.AddAllowedActionOnSheetProtection(Worksheet.SheetProtectionValue.selectLockedCells);
572+
// Override default (technically invalid)
573+
workbook.CurrentWorksheet.RemoveAllowedActionOnSheetProtection(Worksheet.SheetProtectionValue.selectUnlockedCells);
574+
workbook.CurrentWorksheet.UseSheetProtection = true;
575+
}
576+
}
577+
Worksheet givenWorksheet = WriteAndReadWorksheet(workbook, sheetIndex);
578+
Assert.Equal(2, givenWorksheet.SheetProtectionValues.Count);
579+
Assert.True(givenWorksheet.UseSheetProtection);
580+
Assert.Contains(Worksheet.SheetProtectionValue.objects, givenWorksheet.SheetProtectionValues);
581+
Assert.Contains(Worksheet.SheetProtectionValue.scenarios, givenWorksheet.SheetProtectionValues);
582+
Assert.DoesNotContain(Worksheet.SheetProtectionValue.selectLockedCells, givenWorksheet.SheetProtectionValues);
583+
Assert.DoesNotContain(Worksheet.SheetProtectionValue.selectUnlockedCells, givenWorksheet.SheetProtectionValues);
584+
}
585+
559586
[Theory(DisplayName = "Test of the 'SheetProtectionPasswordHash' property when writing and reading a worksheet")]
560587
[InlineData("x", 0)]
561588
[InlineData("@test-1,23", 0)]

0 commit comments

Comments
 (0)