Skip to content

Commit 53c4f76

Browse files
vaadin-botDiegoCardosoclaude
authored
fix: reset freeze pane split positions when switching sheets (#9035) (CP: 25.1) (#9041)
This PR cherry-picks changes from the original PR #9035 to branch 25.1. --- > ## Summary > - Fixes freeze pane state bleeding between sheets when switching tabs in Spreadsheet > - When switching from a sheet with a freeze pane split to one without that split type, the previous sheet's split position was not reset to 0, causing it to persist visually > - Root cause: commit a1963f9 guarded `setHorizontalSplitPosition`/`setVerticalSplitPosition` behind split-exists checks but the `else` branches never explicitly reset the positions to 0 > > Fixes #9006 > > ## Test plan > - [x] New unit tests in `SpreadsheetFactoryTest` verify all freeze pane combinations (both splits, only rows, only columns, none) and the sheet-switching bleed scenario > - [x] Rollback verification: 3 of 5 unit tests fail without the fix, pass with it > - [x] Existing regression tests (`HiddenAndFrozenIT`, `LoadFileWithFrozenPaneScrolledIT`, `MergedCellFrozenIT`) all pass > > 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Diego Cardoso <diego@vaadin.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0743f58 commit 53c4f76

2 files changed

Lines changed: 133 additions & 6 deletions

File tree

vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/SpreadsheetFactory.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,9 +1080,12 @@ static void loadFreezePane(Spreadsheet spreadsheet) {
10801080
.boxed().collect(Collectors.toMap(
10811081
Function.identity(), index -> true)));
10821082
}
1083-
} else if (leftCol > 0) {
1084-
// TODO: should scroll vertically to restore viewport state
1085-
// This needs API on the Spreadsheet side
1083+
} else {
1084+
spreadsheet.setHorizontalSplitPosition(0);
1085+
if (leftCol > 0) {
1086+
// TODO: should scroll horizontally to restore viewport
1087+
// state. This needs API on the Spreadsheet side
1088+
}
10861089
}
10871090

10881091
if (hSplit > 0) {
@@ -1092,9 +1095,12 @@ static void loadFreezePane(Spreadsheet spreadsheet) {
10921095
.collect(Collectors.toMap(Function.identity(),
10931096
index -> true)));
10941097
}
1095-
} else if (topRow > 0) {
1096-
// TODO: should scroll vertically to restore viewport state
1097-
// This needs API on the Spreadsheet side
1098+
} else {
1099+
spreadsheet.setVerticalSplitPosition(0);
1100+
if (topRow > 0) {
1101+
// TODO: should scroll vertically to restore viewport
1102+
// state. This needs API on the Spreadsheet side
1103+
}
10981104
}
10991105
} else {
11001106
spreadsheet.setVerticalSplitPosition(0);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* Copyright 2000-2026 Vaadin Ltd.
3+
*
4+
* This program is available under Vaadin Commercial License and Service Terms.
5+
*
6+
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
7+
* license.
8+
*/
9+
package com.vaadin.flow.component.spreadsheet;
10+
11+
import static org.mockito.Mockito.verify;
12+
import static org.mockito.Mockito.when;
13+
14+
import org.apache.poi.ss.usermodel.Sheet;
15+
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
16+
import org.junit.jupiter.api.BeforeEach;
17+
import org.junit.jupiter.api.Test;
18+
import org.mockito.Mock;
19+
import org.mockito.Mockito;
20+
import org.mockito.MockitoAnnotations;
21+
22+
class SpreadsheetFactoryTest {
23+
24+
@Mock
25+
private Spreadsheet spreadsheet;
26+
27+
private XSSFWorkbook workbook;
28+
29+
@BeforeEach
30+
void setUp() {
31+
MockitoAnnotations.openMocks(this);
32+
workbook = new XSSFWorkbook();
33+
}
34+
35+
@Test
36+
void loadFreezePane_bothSplits_setsBothPositions() {
37+
// POI: createFreezePane(colSplit, rowSplit)
38+
// colSplit → POI verticalSplitPosition (columns)
39+
// rowSplit → POI horizontalSplitPosition (rows)
40+
Sheet sheet = workbook.createSheet();
41+
sheet.createFreezePane(5, 4);
42+
43+
when(spreadsheet.getActiveSheet()).thenReturn(sheet);
44+
45+
SpreadsheetFactory.loadFreezePane(spreadsheet);
46+
47+
// Spreadsheet swaps the naming:
48+
// POI verticalSplit (cols=5) → Spreadsheet horizontalSplitPosition
49+
// POI horizontalSplit (rows=4) → Spreadsheet verticalSplitPosition
50+
verify(spreadsheet).setHorizontalSplitPosition(5);
51+
verify(spreadsheet).setVerticalSplitPosition(4);
52+
}
53+
54+
@Test
55+
void loadFreezePane_onlyFrozenRows_resetsHorizontalToZero() {
56+
// Only frozen rows (POI horizontalSplit), no frozen columns
57+
Sheet sheet = workbook.createSheet();
58+
sheet.createFreezePane(0, 3);
59+
60+
when(spreadsheet.getActiveSheet()).thenReturn(sheet);
61+
62+
SpreadsheetFactory.loadFreezePane(spreadsheet);
63+
64+
verify(spreadsheet).setHorizontalSplitPosition(0);
65+
verify(spreadsheet).setVerticalSplitPosition(3);
66+
}
67+
68+
@Test
69+
void loadFreezePane_onlyFrozenColumns_resetsVerticalToZero() {
70+
// Only frozen columns (POI verticalSplit), no frozen rows
71+
Sheet sheet = workbook.createSheet();
72+
sheet.createFreezePane(2, 0);
73+
74+
when(spreadsheet.getActiveSheet()).thenReturn(sheet);
75+
76+
SpreadsheetFactory.loadFreezePane(spreadsheet);
77+
78+
verify(spreadsheet).setHorizontalSplitPosition(2);
79+
verify(spreadsheet).setVerticalSplitPosition(0);
80+
}
81+
82+
@Test
83+
void loadFreezePane_noFreezePane_resetsBothToZero() {
84+
Sheet sheet = workbook.createSheet();
85+
86+
when(spreadsheet.getActiveSheet()).thenReturn(sheet);
87+
88+
SpreadsheetFactory.loadFreezePane(spreadsheet);
89+
90+
verify(spreadsheet).setHorizontalSplitPosition(0);
91+
verify(spreadsheet).setVerticalSplitPosition(0);
92+
}
93+
94+
@Test
95+
void loadFreezePane_switchingSheets_doesNotBleedState() {
96+
// Simulate switching from a sheet with both splits to one with
97+
// only frozen columns — the vertical split (frozen rows) must
98+
// be reset to 0 and not retain the previous sheet's value.
99+
Sheet bothSplits = workbook.createSheet();
100+
bothSplits.createFreezePane(5, 4);
101+
102+
Sheet onlyColumns = workbook.createSheet();
103+
onlyColumns.createFreezePane(2, 0);
104+
105+
// Load first sheet (both splits)
106+
when(spreadsheet.getActiveSheet()).thenReturn(bothSplits);
107+
SpreadsheetFactory.loadFreezePane(spreadsheet);
108+
109+
verify(spreadsheet).setHorizontalSplitPosition(5);
110+
verify(spreadsheet).setVerticalSplitPosition(4);
111+
112+
Mockito.reset(spreadsheet);
113+
114+
// Switch to second sheet (only columns) — vertical must reset
115+
when(spreadsheet.getActiveSheet()).thenReturn(onlyColumns);
116+
SpreadsheetFactory.loadFreezePane(spreadsheet);
117+
118+
verify(spreadsheet).setHorizontalSplitPosition(2);
119+
verify(spreadsheet).setVerticalSplitPosition(0);
120+
}
121+
}

0 commit comments

Comments
 (0)