Skip to content

Commit 64dfeb6

Browse files
authored
Merge pull request #21 from fahadadeel/main
Add FreezePane Functionality with Properties for Retrieving Freeze Settings
2 parents 6670390 + 85e410c commit 64dfeb6

File tree

2 files changed

+162
-12
lines changed

2 files changed

+162
-12
lines changed

FileFormat.Cells/Worksheet.cs

Lines changed: 111 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,42 @@ public string Name
117117
sheet.Name = value;
118118
}
119119
}
120+
121+
/// <summary>
122+
/// Gets the row index where the pane is frozen in the worksheet.
123+
/// Returns 0 if no rows are frozen.
124+
/// </summary>
125+
/// <remarks>
126+
/// This property retrieves the value of <see cref="VerticalSplit"/> from the Pane element in the SheetView.
127+
/// </remarks>
128+
public int FreezePanesRow
129+
{
130+
get
131+
{
132+
var pane = _worksheetPart.Worksheet.GetFirstChild<SheetViews>()
133+
?.Elements<SheetView>().FirstOrDefault()
134+
?.Elements<Pane>().FirstOrDefault();
135+
return pane != null ? (int)pane.VerticalSplit.Value : 0;
136+
}
137+
}
138+
139+
/// <summary>
140+
/// Gets the column index where the pane is frozen in the worksheet.
141+
/// Returns 0 if no columns are frozen.
142+
/// </summary>
143+
/// <remarks>
144+
/// This property retrieves the value of <see cref="HorizontalSplit"/> from the Pane element in the SheetView.
145+
/// </remarks>
146+
public int FreezePanesColumn
147+
{
148+
get
149+
{
150+
var pane = _worksheetPart.Worksheet.GetFirstChild<SheetViews>()
151+
?.Elements<SheetView>().FirstOrDefault()
152+
?.Elements<Pane>().FirstOrDefault();
153+
return pane != null ? (int)pane.HorizontalSplit.Value : 0;
154+
}
155+
}
120156

121157

122158
/// <summary>
@@ -1049,12 +1085,19 @@ public List<uint> GetHiddenColumns()
10491085
return itemList;
10501086
}
10511087

1052-
10531088
/// <summary>
1054-
/// Freezes the top row of the worksheet.
1089+
/// Freezes the specified rows and/or columns of the worksheet.
10551090
/// </summary>
1056-
public void FreezeFirstRow()
1091+
/// <param name="rowsToFreeze">The number of rows to freeze. Set to 0 if no row freezing is needed.</param>
1092+
/// <param name="columnsToFreeze">The number of columns to freeze. Set to 0 if no column freezing is needed.</param>
1093+
public void FreezePane(int rowsToFreeze, int columnsToFreeze)
10571094
{
1095+
// Ensure we are freezing at least one row or column
1096+
if (rowsToFreeze == 0 && columnsToFreeze == 0)
1097+
{
1098+
return; // No freeze needed, exit the method.
1099+
}
1100+
10581101
// Retrieve or create the SheetViews element
10591102
SheetViews sheetViews = _worksheetPart.Worksheet.GetFirstChild<SheetViews>();
10601103

@@ -1080,24 +1123,42 @@ public void FreezeFirstRow()
10801123
existingPane.Remove();
10811124
}
10821125

1083-
// Define freeze pane settings for freezing the top row
1126+
// Calculate the top left cell after the freeze
1127+
string topLeftCell = GetTopLeftCell(rowsToFreeze, columnsToFreeze);
1128+
1129+
// Define freeze pane settings dynamically based on the rows and columns to freeze
10841130
Pane pane = new Pane
10851131
{
1086-
VerticalSplit = 1D, // Split below the first row
1087-
TopLeftCell = "A2", // Top left cell after freeze
1088-
ActivePane = PaneValues.BottomLeft,
1132+
VerticalSplit = rowsToFreeze > 0 ? (double)rowsToFreeze : 0D,
1133+
HorizontalSplit = columnsToFreeze > 0 ? (double)columnsToFreeze : 0D,
1134+
TopLeftCell = topLeftCell,
1135+
ActivePane = PaneValues.BottomRight,
10891136
State = PaneStateValues.Frozen
10901137
};
10911138

1139+
// Adjust active pane based on what is being frozen
1140+
if (rowsToFreeze > 0 && columnsToFreeze > 0)
1141+
{
1142+
pane.ActivePane = PaneValues.BottomRight; // Both rows and columns
1143+
}
1144+
else if (rowsToFreeze > 0)
1145+
{
1146+
pane.ActivePane = PaneValues.BottomLeft; // Only rows
1147+
}
1148+
else if (columnsToFreeze > 0)
1149+
{
1150+
pane.ActivePane = PaneValues.TopRight; // Only columns
1151+
}
1152+
10921153
// Insert the Pane as the first child of SheetView
10931154
sheetView.InsertAt(pane, 0);
10941155

10951156
// Add the selection for the frozen pane
10961157
Selection selection = new Selection()
10971158
{
1098-
Pane = PaneValues.BottomLeft,
1099-
ActiveCell = "A2",
1100-
SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A2" }
1159+
Pane = pane.ActivePane,
1160+
ActiveCell = topLeftCell,
1161+
SequenceOfReferences = new ListValue<StringValue>() { InnerText = topLeftCell }
11011162
};
11021163

11031164
// Ensure selection comes after the pane
@@ -1107,6 +1168,46 @@ public void FreezeFirstRow()
11071168
_worksheetPart.Worksheet.Save();
11081169
}
11091170

1171+
/// <summary>
1172+
/// Determines the top left cell after the freeze pane based on rows and columns to freeze.
1173+
/// </summary>
1174+
/// <param name="rowsToFreeze">The number of rows to freeze.</param>
1175+
/// <param name="columnsToFreeze">The number of columns to freeze.</param>
1176+
/// <returns>The top left cell reference as a string (e.g., "B2").</returns>
1177+
private string GetTopLeftCell(int rowsToFreeze, int columnsToFreeze)
1178+
{
1179+
// Default top left cell is A1
1180+
if (rowsToFreeze == 0 && columnsToFreeze == 0)
1181+
{
1182+
return "A1";
1183+
}
1184+
1185+
// Calculate column part (A, B, C, etc.) based on columns to freeze
1186+
string columnLetter = columnsToFreeze > 0 ? GetColumnLetter(columnsToFreeze + 1) : "A";
1187+
1188+
// Calculate row number based on rows to freeze
1189+
int rowNumber = rowsToFreeze > 0 ? rowsToFreeze + 1 : 1;
1190+
1191+
return $"{columnLetter}{rowNumber}";
1192+
}
1193+
1194+
/// <summary>
1195+
/// Converts a column index (1-based) to an Excel column letter (A, B, C, ..., Z, AA, AB, etc.).
1196+
/// </summary>
1197+
/// <param name="columnIndex">The 1-based index of the column.</param>
1198+
/// <returns>The corresponding column letter as a string.</returns>
1199+
private string GetColumnLetter(int columnIndex)
1200+
{
1201+
string columnLetter = string.Empty;
1202+
while (columnIndex > 0)
1203+
{
1204+
columnIndex--;
1205+
columnLetter = (char)('A' + (columnIndex % 26)) + columnLetter;
1206+
columnIndex /= 26;
1207+
}
1208+
return columnLetter;
1209+
}
1210+
11101211
/// <summary>
11111212
/// Hides a specific row in the worksheet.
11121213
/// </summary>

FileFormat.Cells_Tests/UnitTest1.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-

2-
using FileFormat.Cells;
1+
using FileFormat.Cells;
32
namespace FileFormat.Cells_Tests
43
{
54
[TestClass]
@@ -473,6 +472,56 @@ public void NumericValidationRule_CreatesCorrectTypeAndValues()
473472
Assert.AreEqual(maxValue, rule.MaxValue);
474473
}
475474

475+
[TestMethod]
476+
public void FreezePane_ShouldSetCorrectFreezePanesRow()
477+
{
478+
// Arrange
479+
int expectedRows = 2;
480+
int expectedColumns = 1;
481+
using (Workbook wb = new Workbook(testFilePath))
482+
{
483+
Worksheet firstSheet = wb.Worksheets.First();
484+
485+
firstSheet.FreezePane(expectedRows, expectedColumns);
486+
487+
wb.Save();
488+
}
489+
490+
using (Workbook wb = new Workbook(testFilePath))
491+
{
492+
Worksheet firstSheet = wb.Worksheets.First();
493+
494+
// Assert
495+
Assert.AreEqual(expectedRows, firstSheet.FreezePanesRow, "FreezePanesColumn should match the columns frozen.");
496+
}
497+
}
498+
499+
[TestMethod]
500+
public void FreezePane_ShouldSetCorrectFreezePanesColumn()
501+
{
502+
// Arrange
503+
int expectedRows = 2;
504+
int expectedColumns = 1;
505+
using (Workbook wb = new Workbook(testFilePath))
506+
{
507+
Worksheet firstSheet = wb.Worksheets.First();
508+
509+
firstSheet.FreezePane(expectedRows, expectedColumns);
510+
511+
wb.Save();
512+
}
513+
514+
using (Workbook wb = new Workbook(testFilePath))
515+
{
516+
Worksheet firstSheet = wb.Worksheets.First();
517+
518+
// Assert
519+
Assert.AreEqual(expectedColumns, firstSheet.FreezePanesColumn, "FreezePanesColumn should match the columns frozen.");
520+
}
521+
522+
}
523+
524+
476525
[TestMethod]
477526
public void CustomFormulaValidationRule_CreatesCorrectFormula()
478527
{

0 commit comments

Comments
 (0)