Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ooxml/XSSF/UserModel/XSSFSheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public partial class XSSFSheet : POIXMLDocumentPart, ISheet
private List<CellRangeAddress> arrayFormulas;
private readonly XSSFDataValidationHelper dataValidationHelper;
private XSSFDrawing drawing = null;
private bool _worksheetLoaded = false;
private volatile bool _worksheetLoaded = false;
private readonly object _loadLock = new object();
internal int _parseCount = 0;

Expand Down
66 changes: 66 additions & 0 deletions testcases/ooxml/XSSF/UserModel/TestXSSFSheetLazyLoad.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,5 +214,71 @@ public void MultipleSheetsSomeAccessedSomeNot()
Assert.That(sheet1._parseCount, Is.EqualTo(1), "sheet1 was accessed, should be parsed once");
Assert.That(sheet2._parseCount, Is.EqualTo(0), "sheet2 was not accessed, should not be parsed");
}

[Test]
public void SaveWithoutAccessPreservesUntouchedSheets()
{
// Create a 3-sheet workbook with distinct data
byte[] originalBytes;
using (var wb = new XSSFWorkbook())
{
for (int i = 0; i < 3; i++)
{
var s = wb.CreateSheet($"Sheet{i}");
s.CreateRow(0).CreateCell(0).SetCellValue($"Original{i}");
s.CreateRow(1).CreateCell(0).SetCellValue(i * 100.0);
}
using var ms = new MemoryStream();
wb.Write(ms);
originalBytes = ms.ToArray();
}

// Open, touch only Sheet1, modify it, and save
byte[] savedBytes;
using (var ms = new MemoryStream(originalBytes))
using (var wb = new XSSFWorkbook(ms))
{
var sheet0 = (XSSFSheet)wb.GetSheetAt(0);
var sheet1 = (XSSFSheet)wb.GetSheetAt(1);
var sheet2 = (XSSFSheet)wb.GetSheetAt(2);

// Only access sheet1 — sheets 0 and 2 should never be parsed
sheet1.GetRow(0).GetCell(0).SetCellValue("Modified1");

Assert.That(sheet0._parseCount, Is.EqualTo(0), "sheet0 should not be parsed");
Assert.That(sheet1._parseCount, Is.EqualTo(1), "sheet1 should be parsed once");
Assert.That(sheet2._parseCount, Is.EqualTo(0), "sheet2 should not be parsed");

using var outMs = new MemoryStream();
wb.Write(outMs);
savedBytes = outMs.ToArray();
}

// Re-open and verify all sheets survived the roundtrip
using (var ms = new MemoryStream(savedBytes))
using (var wb = new XSSFWorkbook(ms))
{
// Sheet0: untouched — should have original data
var s0 = wb.GetSheetAt(0);
Assert.That(s0.GetRow(0).GetCell(0).StringCellValue, Is.EqualTo("Original0"),
"Untouched sheet0 should preserve original data");
Assert.That(s0.GetRow(1).GetCell(0).NumericCellValue, Is.EqualTo(0.0),
"Untouched sheet0 row 1 should preserve original data");

// Sheet1: modified
var s1 = wb.GetSheetAt(1);
Assert.That(s1.GetRow(0).GetCell(0).StringCellValue, Is.EqualTo("Modified1"),
"Modified sheet1 should have new value");
Assert.That(s1.GetRow(1).GetCell(0).NumericCellValue, Is.EqualTo(100.0),
"Unmodified row in sheet1 should preserve original data");

// Sheet2: untouched — should have original data
var s2 = wb.GetSheetAt(2);
Assert.That(s2.GetRow(0).GetCell(0).StringCellValue, Is.EqualTo("Original2"),
"Untouched sheet2 should preserve original data");
Assert.That(s2.GetRow(1).GetCell(0).NumericCellValue, Is.EqualTo(200.0),
"Untouched sheet2 row 1 should preserve original data");
}
}
}
}
Loading