Skip to content

Commit

Permalink
Merge pull request #21 from fahadadeel/main
Browse files Browse the repository at this point in the history
Add FreezePane Functionality with Properties for Retrieving Freeze Settings
  • Loading branch information
fahadadeel authored Oct 16, 2024
2 parents 6670390 + 85e410c commit 64dfeb6
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 12 deletions.
121 changes: 111 additions & 10 deletions FileFormat.Cells/Worksheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,42 @@ public string Name
sheet.Name = value;
}
}

/// <summary>
/// Gets the row index where the pane is frozen in the worksheet.
/// Returns 0 if no rows are frozen.
/// </summary>
/// <remarks>
/// This property retrieves the value of <see cref="VerticalSplit"/> from the Pane element in the SheetView.
/// </remarks>
public int FreezePanesRow
{
get
{
var pane = _worksheetPart.Worksheet.GetFirstChild<SheetViews>()
?.Elements<SheetView>().FirstOrDefault()
?.Elements<Pane>().FirstOrDefault();
return pane != null ? (int)pane.VerticalSplit.Value : 0;
}
}

/// <summary>
/// Gets the column index where the pane is frozen in the worksheet.
/// Returns 0 if no columns are frozen.
/// </summary>
/// <remarks>
/// This property retrieves the value of <see cref="HorizontalSplit"/> from the Pane element in the SheetView.
/// </remarks>
public int FreezePanesColumn
{
get
{
var pane = _worksheetPart.Worksheet.GetFirstChild<SheetViews>()
?.Elements<SheetView>().FirstOrDefault()
?.Elements<Pane>().FirstOrDefault();
return pane != null ? (int)pane.HorizontalSplit.Value : 0;
}
}


/// <summary>
Expand Down Expand Up @@ -1049,12 +1085,19 @@ public List<uint> GetHiddenColumns()
return itemList;
}


/// <summary>
/// Freezes the top row of the worksheet.
/// Freezes the specified rows and/or columns of the worksheet.
/// </summary>
public void FreezeFirstRow()
/// <param name="rowsToFreeze">The number of rows to freeze. Set to 0 if no row freezing is needed.</param>
/// <param name="columnsToFreeze">The number of columns to freeze. Set to 0 if no column freezing is needed.</param>
public void FreezePane(int rowsToFreeze, int columnsToFreeze)
{
// Ensure we are freezing at least one row or column
if (rowsToFreeze == 0 && columnsToFreeze == 0)
{
return; // No freeze needed, exit the method.
}

// Retrieve or create the SheetViews element
SheetViews sheetViews = _worksheetPart.Worksheet.GetFirstChild<SheetViews>();

Expand All @@ -1080,24 +1123,42 @@ public void FreezeFirstRow()
existingPane.Remove();
}

// Define freeze pane settings for freezing the top row
// Calculate the top left cell after the freeze
string topLeftCell = GetTopLeftCell(rowsToFreeze, columnsToFreeze);

// Define freeze pane settings dynamically based on the rows and columns to freeze
Pane pane = new Pane
{
VerticalSplit = 1D, // Split below the first row
TopLeftCell = "A2", // Top left cell after freeze
ActivePane = PaneValues.BottomLeft,
VerticalSplit = rowsToFreeze > 0 ? (double)rowsToFreeze : 0D,
HorizontalSplit = columnsToFreeze > 0 ? (double)columnsToFreeze : 0D,
TopLeftCell = topLeftCell,
ActivePane = PaneValues.BottomRight,
State = PaneStateValues.Frozen
};

// Adjust active pane based on what is being frozen
if (rowsToFreeze > 0 && columnsToFreeze > 0)
{
pane.ActivePane = PaneValues.BottomRight; // Both rows and columns
}
else if (rowsToFreeze > 0)
{
pane.ActivePane = PaneValues.BottomLeft; // Only rows
}
else if (columnsToFreeze > 0)
{
pane.ActivePane = PaneValues.TopRight; // Only columns
}

// Insert the Pane as the first child of SheetView
sheetView.InsertAt(pane, 0);

// Add the selection for the frozen pane
Selection selection = new Selection()
{
Pane = PaneValues.BottomLeft,
ActiveCell = "A2",
SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A2" }
Pane = pane.ActivePane,
ActiveCell = topLeftCell,
SequenceOfReferences = new ListValue<StringValue>() { InnerText = topLeftCell }
};

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

/// <summary>
/// Determines the top left cell after the freeze pane based on rows and columns to freeze.
/// </summary>
/// <param name="rowsToFreeze">The number of rows to freeze.</param>
/// <param name="columnsToFreeze">The number of columns to freeze.</param>
/// <returns>The top left cell reference as a string (e.g., "B2").</returns>
private string GetTopLeftCell(int rowsToFreeze, int columnsToFreeze)
{
// Default top left cell is A1
if (rowsToFreeze == 0 && columnsToFreeze == 0)
{
return "A1";
}

// Calculate column part (A, B, C, etc.) based on columns to freeze
string columnLetter = columnsToFreeze > 0 ? GetColumnLetter(columnsToFreeze + 1) : "A";

// Calculate row number based on rows to freeze
int rowNumber = rowsToFreeze > 0 ? rowsToFreeze + 1 : 1;

return $"{columnLetter}{rowNumber}";
}

/// <summary>
/// Converts a column index (1-based) to an Excel column letter (A, B, C, ..., Z, AA, AB, etc.).
/// </summary>
/// <param name="columnIndex">The 1-based index of the column.</param>
/// <returns>The corresponding column letter as a string.</returns>
private string GetColumnLetter(int columnIndex)
{
string columnLetter = string.Empty;
while (columnIndex > 0)
{
columnIndex--;
columnLetter = (char)('A' + (columnIndex % 26)) + columnLetter;
columnIndex /= 26;
}
return columnLetter;
}

/// <summary>
/// Hides a specific row in the worksheet.
/// </summary>
Expand Down
53 changes: 51 additions & 2 deletions FileFormat.Cells_Tests/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

using FileFormat.Cells;
using FileFormat.Cells;
namespace FileFormat.Cells_Tests
{
[TestClass]
Expand Down Expand Up @@ -473,6 +472,56 @@ public void NumericValidationRule_CreatesCorrectTypeAndValues()
Assert.AreEqual(maxValue, rule.MaxValue);
}

[TestMethod]
public void FreezePane_ShouldSetCorrectFreezePanesRow()
{
// Arrange
int expectedRows = 2;
int expectedColumns = 1;
using (Workbook wb = new Workbook(testFilePath))
{
Worksheet firstSheet = wb.Worksheets.First();

firstSheet.FreezePane(expectedRows, expectedColumns);

wb.Save();
}

using (Workbook wb = new Workbook(testFilePath))
{
Worksheet firstSheet = wb.Worksheets.First();

// Assert
Assert.AreEqual(expectedRows, firstSheet.FreezePanesRow, "FreezePanesColumn should match the columns frozen.");
}
}

[TestMethod]
public void FreezePane_ShouldSetCorrectFreezePanesColumn()
{
// Arrange
int expectedRows = 2;
int expectedColumns = 1;
using (Workbook wb = new Workbook(testFilePath))
{
Worksheet firstSheet = wb.Worksheets.First();

firstSheet.FreezePane(expectedRows, expectedColumns);

wb.Save();
}

using (Workbook wb = new Workbook(testFilePath))
{
Worksheet firstSheet = wb.Worksheets.First();

// Assert
Assert.AreEqual(expectedColumns, firstSheet.FreezePanesColumn, "FreezePanesColumn should match the columns frozen.");
}

}


[TestMethod]
public void CustomFormulaValidationRule_CreatesCorrectFormula()
{
Expand Down

0 comments on commit 64dfeb6

Please sign in to comment.