Skip to content

Commit 60efe0c

Browse files
[t:DCWIbRRX] added freeze rows and cols
1 parent 933e902 commit 60efe0c

File tree

2 files changed

+126
-4
lines changed

2 files changed

+126
-4
lines changed

Test/XLSXWriterTest.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,108 @@ public function testMarkMergedCells() {
117117
@unlink($filename);
118118
}
119119

120+
/**
121+
* @dataProvider getFreezeCellsScenarios
122+
*/
123+
public function testFreezeCells($freeze_cols, $freeze_rows, $expected_active_cells, $expected_pane) {
124+
$filename = tempnam("/tmp", "xlsx_writer");
125+
126+
$header = ['0'=>'string','1'=>'string','2'=>'string','3'=>'string'];
127+
$sheet = [
128+
['55','66','77','88'],
129+
['10','11','12','13'],
130+
];
131+
132+
$col_options = ['freeze_columns' => $freeze_cols, 'freeze_rows' => $freeze_rows];
133+
134+
$xlsx_writer = new XLSXWriter();
135+
$xlsx_writer->writeSheetHeader('mysheet', $header, $format = 'xlsx', $delimiter = ';', $subheader = NULL, $col_options);
136+
$xlsx_writer->writeSheetRow('mysheet', $sheet[0]);
137+
$xlsx_writer->writeSheetRow('mysheet', $sheet[1]);
138+
$xlsx_writer->writeToFile($filename);
139+
140+
$zip = new ZipArchive();
141+
$r = $zip->open($filename);
142+
$this->assertTrue($r);
143+
144+
$this->assertNotEmpty(($zip->numFiles));
145+
146+
for($z=0; $z < $zip->numFiles; $z++) {
147+
$inside_zip_filename = $zip->getNameIndex($z);
148+
$sheet_xml = $zip->getFromName($inside_zip_filename);
149+
if (preg_match("/sheet(\d+).xml/", basename($inside_zip_filename))) {
150+
$xml = new SimpleXMLElement($sheet_xml);
151+
$sheet_view = $xml->sheetViews->sheetView;
152+
153+
if (!empty($expected_pane)) {
154+
$pane = $sheet_view->pane;
155+
foreach ($expected_pane as $expected_key => $expected_value) {
156+
$attribute = (string) $pane[0][$expected_key];
157+
$this->assertEquals($expected_value, $attribute);
158+
}
159+
}
160+
161+
$selections = $sheet_view->selection;
162+
for ($i = 0; $i < count($expected_active_cells); $i++) {
163+
$this->assertNotEmpty($selections[$i]);
164+
$this->assertEquals($expected_active_cells[$i]['cell'], $selections[$i]['activeCell']);
165+
$this->assertEquals($expected_active_cells[$i]['cell'], $selections[$i]['sqref']);
166+
$this->assertEquals($expected_active_cells[$i]['pane'], $selections[$i]['pane']);
167+
}
168+
}
169+
}
170+
171+
$zip->close();
172+
@unlink($filename);
173+
}
174+
175+
public static function getFreezeCellsScenarios() {
176+
return [
177+
"Not frozen" => [
178+
$freeze_cols = false,
179+
$freeze_rows = false,
180+
$expected_active_cells = [["cell" => "A1", "pane" => "topLeft"]],
181+
$expected_pane = [],
182+
],
183+
"Frozen Col B and Row 2" => [
184+
$freeze_cols = 1,
185+
$freeze_rows = 1,
186+
$expected_active_cells = [["cell" => "A2", "pane" => "topRight"], ["cell" => "B1", "pane" => "bottomLeft"], ["cell" => "B2", "pane" => "bottomRight"]],
187+
$expected_pane = ["ySplit" => $freeze_rows, "xSplit" => $freeze_cols, "topLeftCell" => "B2", "activePane" => "bottomRight"],
188+
],
189+
"Frozen Col B" => [
190+
$freeze_cols = 1,
191+
$freeze_rows = false,
192+
$expected_active_cells = [["cell" => "B1", "pane" => "topRight"]],
193+
$expected_pane = ["xSplit" => $freeze_cols, "topLeftCell" => "B1", "activePane" => "topRight"],
194+
],
195+
"Frozen Row 2" => [
196+
$freeze_cols = false,
197+
$freeze_rows = 1,
198+
$expected_active_cells = [["cell" => "A2", "pane" => "bottomLeft"]],
199+
$expected_pane = ["ySplit" => $freeze_rows, "topLeftCell" => "A2", "activePane" => "bottomLeft"],
200+
],
201+
"Frozen Col A and Row 1" => [
202+
$freeze_cols = 0,
203+
$freeze_rows = 0,
204+
$expected_active_cells = [["cell" => "A1", "pane" => "topRight"], ["cell" => "A1", "pane" => "bottomLeft"], ["cell" => "A1", "pane" => "bottomRight"]],
205+
$expected_pane = ["ySplit" => $freeze_rows, "xSplit" => $freeze_cols, "topLeftCell" => "A1", "activePane" => "bottomRight"],
206+
],
207+
"Frozen Col A" => [
208+
$freeze_cols = 0,
209+
$freeze_rows = false,
210+
$expected_active_cells = [["cell" => "A1", "pane" => "topRight"]],
211+
$expected_pane = ["xSplit" => $freeze_cols, "topLeftCell" => "A1", "activePane" => "topRight"],
212+
],
213+
"Frozen Row 1" => [
214+
$freeze_cols = false,
215+
$freeze_rows = 0,
216+
$expected_active_cells = [["cell" => "A1", "pane" => "bottomLeft"]],
217+
$expected_pane = ["ySplit" => $freeze_rows, "topLeftCell" => "A1", "activePane" => "bottomLeft"],
218+
],
219+
];
220+
}
221+
120222
private function stripCellsFromSheetXML($sheet_xml) {
121223
$output = [];
122224

xlsxwriter.class.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public function writeToFile($filename)
118118
$zip->close();
119119
}
120120

121-
protected function initializeSheet($sheet_name)
121+
protected function initializeSheet($sheet_name, $freeze_rows=false, $freeze_columns=false)
122122
{
123123
//if already initialized
124124
if ($this->current_sheet==$sheet_name || isset($this->sheets[$sheet_name]))
@@ -136,6 +136,8 @@ protected function initializeSheet($sheet_name)
136136
'merge_cells' => [],
137137
'max_cell_tag_start' => 0,
138138
'max_cell_tag_end' => 0,
139+
'freeze_rows' => $freeze_rows,
140+
'freeze_columns' => $freeze_columns,
139141
'finalized' => false,
140142
];
141143
$sheet = &$this->sheets[$sheet_name];
@@ -151,7 +153,22 @@ protected function initializeSheet($sheet_name)
151153
$sheet->max_cell_tag_end = $sheet->file_writer->ftell();
152154
$sheet->file_writer->write( '<sheetViews>');
153155
$sheet->file_writer->write( '<sheetView colorId="64" defaultGridColor="true" rightToLeft="false" showFormulas="false" showGridLines="true" showOutlineSymbols="true" showRowColHeaders="true" showZeros="true" tabSelected="' . $tabselected . '" topLeftCell="A1" view="normal" windowProtection="false" workbookViewId="0" zoomScale="100" zoomScaleNormal="100" zoomScalePageLayoutView="100">');
154-
$sheet->file_writer->write( '<selection activeCell="A1" activeCellId="0" pane="topLeft" sqref="A1"/>');
156+
157+
if ($sheet->freeze_rows !== false && $sheet->freeze_columns !== false) {
158+
$sheet->file_writer->write( '<pane ySplit="'.$sheet->freeze_rows.'" xSplit="'.$sheet->freeze_columns.'" topLeftCell="'.self::xlsCell($sheet->freeze_rows, $sheet->freeze_columns).'" activePane="bottomRight" state="frozen"/>');
159+
$sheet->file_writer->write( '<selection activeCell="'.self::xlsCell($sheet->freeze_rows, 0).'" activeCellId="0" pane="topRight" sqref="'.self::xlsCell($sheet->freeze_rows, 0).'"/>');
160+
$sheet->file_writer->write( '<selection activeCell="'.self::xlsCell(0, $sheet->freeze_columns).'" activeCellId="0" pane="bottomLeft" sqref="'.self::xlsCell(0, $sheet->freeze_columns).'"/>');
161+
$sheet->file_writer->write( '<selection activeCell="'.self::xlsCell($sheet->freeze_rows, $sheet->freeze_columns).'" activeCellId="0" pane="bottomRight" sqref="'.self::xlsCell($sheet->freeze_rows, $sheet->freeze_columns).'"/>');
162+
} elseif ($sheet->freeze_rows !== false) {
163+
$sheet->file_writer->write( '<pane ySplit="'.$sheet->freeze_rows.'" topLeftCell="'.self::xlsCell($sheet->freeze_rows, 0).'" activePane="bottomLeft" state="frozen"/>');
164+
$sheet->file_writer->write( '<selection activeCell="'.self::xlsCell($sheet->freeze_rows, 0).'" activeCellId="0" pane="bottomLeft" sqref="'.self::xlsCell($sheet->freeze_rows, 0).'"/>');
165+
} elseif ($sheet->freeze_columns !== false) {
166+
$sheet->file_writer->write( '<pane xSplit="'.$sheet->freeze_columns.'" topLeftCell="'.self::xlsCell(0, $sheet->freeze_columns).'" activePane="topRight" state="frozen"/>');
167+
$sheet->file_writer->write( '<selection activeCell="'.self::xlsCell(0, $sheet->freeze_columns).'" activeCellId="0" pane="topRight" sqref="'.self::xlsCell(0, $sheet->freeze_columns).'"/>');
168+
} else { // not frozen
169+
$sheet->file_writer->write( '<selection activeCell="A1" activeCellId="0" pane="topLeft" sqref="A1"/>');
170+
}
171+
155172
$sheet->file_writer->write( '</sheetView>');
156173
$sheet->file_writer->write( '</sheetViews>');
157174
$sheet->file_writer->write( '<cols>');
@@ -160,7 +177,7 @@ protected function initializeSheet($sheet_name)
160177
$sheet->file_writer->write( '<sheetData>');
161178
}
162179

163-
public function writeSheetHeader($sheet_name, array $header_types, $format = 'xlsx', $delimiter = ';', $subheader = NULL) {
180+
public function writeSheetHeader($sheet_name, array $header_types, $format = 'xlsx', $delimiter = ';', $subheader = NULL, $col_options = []) {
164181
if (empty($sheet_name) || empty($header_types) || !empty($this->sheets[$sheet_name])) {
165182
return;
166183
}
@@ -184,7 +201,10 @@ public function writeSheetHeader($sheet_name, array $header_types, $format = 'xl
184201
$start = 0;
185202
}
186203

187-
self::initializeSheet($sheet_name);
204+
$freeze_rows = (array_key_exists('freeze_rows', $col_options) && $col_options['freeze_rows'] !== false) ? intval($col_options['freeze_rows']) : false;
205+
$freeze_columns = (array_key_exists('freeze_columns', $col_options) && $col_options['freeze_columns'] !== false) ? intval($col_options['freeze_columns']) : false;
206+
207+
self::initializeSheet($sheet_name, $freeze_rows, $freeze_columns);
188208
$sheet = &$this->sheets[$sheet_name];
189209
$sheet->cell_formats = array_values($header_types);
190210
$header_row = array_keys($header_types);

0 commit comments

Comments
 (0)