parent
eb58563b4b
commit
11b055b29f
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
### Added
|
||||
|
||||
- Support to write merged cells in ODS format [#287](https://github.com/PHPOffice/PhpSpreadsheet/issues/287)
|
||||
- Able to set the `topLeftCell` in freeze panes [#261](https://github.com/PHPOffice/PhpSpreadsheet/pull/261)
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -4488,9 +4488,17 @@ class Xls extends BaseReader
|
|||
// offset: 2; size: 2; position of horizontal split
|
||||
$py = self::getUInt2d($recordData, 2);
|
||||
|
||||
// offset: 4; size: 2; top most visible row in the bottom pane
|
||||
$rwTop = self::getUInt2d($recordData, 4);
|
||||
|
||||
// offset: 6; size: 2; first visible left column in the right pane
|
||||
$colLeft = self::getUInt2d($recordData, 6);
|
||||
|
||||
if ($this->frozen) {
|
||||
// frozen panes
|
||||
$this->phpSheet->freezePane(Coordinate::stringFromColumnIndex($px + 1) . ($py + 1));
|
||||
$cell = Coordinate::stringFromColumnIndex($px + 1) . ($py + 1);
|
||||
$topLeftCell = Coordinate::stringFromColumnIndex($colLeft + 1) . ($rwTop + 1);
|
||||
$this->phpSheet->freezePane($cell, $topLeftCell);
|
||||
}
|
||||
// unfrozen panes; split windows; not supported by PhpSpreadsheet core
|
||||
}
|
||||
|
|
|
@ -720,22 +720,23 @@ class Xlsx extends BaseReader
|
|||
$docSheet->setRightToLeft(self::boolean((string) $xmlSheet->sheetViews->sheetView['rightToLeft']));
|
||||
}
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane)) {
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
|
||||
$docSheet->freezePane((string) $xmlSheet->sheetViews->sheetView->pane['topLeftCell']);
|
||||
} else {
|
||||
$xSplit = 0;
|
||||
$ySplit = 0;
|
||||
$topLeftCell = null;
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) {
|
||||
$xSplit = 1 + (int) ($xmlSheet->sheetViews->sheetView->pane['xSplit']);
|
||||
$xSplit = (int) ($xmlSheet->sheetViews->sheetView->pane['xSplit']);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) {
|
||||
$ySplit = 1 + (int) ($xmlSheet->sheetViews->sheetView->pane['ySplit']);
|
||||
$ySplit = (int) ($xmlSheet->sheetViews->sheetView->pane['ySplit']);
|
||||
}
|
||||
|
||||
$docSheet->freezePaneByColumnAndRow($xSplit + 1, $ySplit);
|
||||
if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) {
|
||||
$topLeftCell = (string) $xmlSheet->sheetViews->sheetView->pane['topLeftCell'];
|
||||
}
|
||||
|
||||
$docSheet->freezePane(Coordinate::stringFromColumnIndex($xSplit + 1) . ($ySplit + 1), $topLeftCell);
|
||||
}
|
||||
|
||||
if (isset($xmlSheet->sheetViews->sheetView->selection)) {
|
||||
|
|
|
@ -576,8 +576,14 @@ class ReferenceHelper
|
|||
}
|
||||
|
||||
// Update worksheet: freeze pane
|
||||
if ($pSheet->getFreezePane() != '') {
|
||||
$pSheet->freezePane($this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows));
|
||||
if ($pSheet->getFreezePane()) {
|
||||
$splitCell = $pSheet->getFreezePane();
|
||||
$topLeftCell = $pSheet->getTopLeftCell();
|
||||
|
||||
$splitCell = $this->updateCellReference($splitCell, $pBefore, $pNumCols, $pNumRows);
|
||||
$topLeftCell = $this->updateCellReference($topLeftCell, $pBefore, $pNumCols, $pNumRows);
|
||||
|
||||
$pSheet->freezePane($splitCell, $topLeftCell);
|
||||
}
|
||||
|
||||
// Page setup
|
||||
|
|
|
@ -201,9 +201,16 @@ class Worksheet implements IComparable
|
|||
/**
|
||||
* Freeze pane.
|
||||
*
|
||||
* @var string
|
||||
* @var null|string
|
||||
*/
|
||||
private $freezePane = '';
|
||||
private $freezePane;
|
||||
|
||||
/**
|
||||
* Default position of the right bottom pane.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
private $topLeftCell;
|
||||
|
||||
/**
|
||||
* Show gridlines?
|
||||
|
@ -1975,27 +1982,33 @@ class Worksheet implements IComparable
|
|||
/**
|
||||
* Freeze Pane.
|
||||
*
|
||||
* @param string $pCell Cell (i.e. A2)
|
||||
* Examples:
|
||||
* A2 will freeze the rows above cell A2 (i.e row 1)
|
||||
* B1 will freeze the columns to the left of cell B1 (i.e column A)
|
||||
* B2 will freeze the rows above and to the left of cell A2
|
||||
* (i.e row 1 and column A)
|
||||
*
|
||||
* - A2 will freeze the rows above cell A2 (i.e row 1)
|
||||
* - B1 will freeze the columns to the left of cell B1 (i.e column A)
|
||||
* - B2 will freeze the rows above and to the left of cell A2 (i.e row 1 and column A)
|
||||
*
|
||||
* @param null|string $cell Position of the split
|
||||
* @param null|string $topLeftCell default position of the right bottom pane
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
*/
|
||||
public function freezePane($pCell)
|
||||
public function freezePane($cell, $topLeftCell = null)
|
||||
{
|
||||
// Uppercase coordinate
|
||||
$pCell = strtoupper($pCell);
|
||||
if (strpos($pCell, ':') === false && strpos($pCell, ',') === false) {
|
||||
$this->freezePane = $pCell;
|
||||
} else {
|
||||
if (is_string($cell) && (strpos($cell, ':') !== false || strpos($cell, ',') !== false)) {
|
||||
throw new Exception('Freeze pane can not be set on a range of cells.');
|
||||
}
|
||||
|
||||
if ($cell !== null && $topLeftCell === null) {
|
||||
$coordinate = Coordinate::coordinateFromString($cell);
|
||||
$topLeftCell = $coordinate[0] . ($coordinate[1] + 1);
|
||||
}
|
||||
|
||||
$this->freezePane = $cell;
|
||||
$this->topLeftCell = $topLeftCell;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -2005,8 +2018,6 @@ class Worksheet implements IComparable
|
|||
* @param int $columnIndex Numeric column coordinate of the cell
|
||||
* @param int $row Numeric row coordinate of the cell
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
*/
|
||||
public function freezePaneByColumnAndRow($columnIndex, $row)
|
||||
|
@ -2021,7 +2032,17 @@ class Worksheet implements IComparable
|
|||
*/
|
||||
public function unfreezePane()
|
||||
{
|
||||
return $this->freezePane('');
|
||||
return $this->freezePane(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default position of the right bottom pane.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTopLeftCell()
|
||||
{
|
||||
return $this->topLeftCell;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2622,6 +2643,7 @@ class Worksheet implements IComparable
|
|||
// Identify the range that we need to extract from the worksheet
|
||||
$maxCol = $this->getHighestColumn();
|
||||
$maxRow = $this->getHighestRow();
|
||||
|
||||
// Return
|
||||
return $this->rangeToArray('A1:' . $maxCol . $maxRow, $nullValue, $calculateFormulas, $formatData, $returnCellRef);
|
||||
}
|
||||
|
|
|
@ -1589,10 +1589,15 @@ class Worksheet extends BIFFwriter
|
|||
private function writePanes()
|
||||
{
|
||||
$panes = [];
|
||||
if ($freezePane = $this->phpSheet->getFreezePane()) {
|
||||
list($column, $row) = Coordinate::coordinateFromString($freezePane);
|
||||
$panes[0] = $row - 1;
|
||||
$panes[1] = Coordinate::columnIndexFromString($column) - 1;
|
||||
if ($this->phpSheet->getFreezePane()) {
|
||||
list($column, $row) = Coordinate::coordinateFromString($this->phpSheet->getFreezePane());
|
||||
$panes[0] = Coordinate::columnIndexFromString($column) - 1;
|
||||
$panes[1] = $row - 1;
|
||||
|
||||
list($leftMostColumn, $topRow) = Coordinate::coordinateFromString($this->phpSheet->getTopLeftCell());
|
||||
//Coordinates are zero-based in xls files
|
||||
$panes[2] = $topRow - 1;
|
||||
$panes[3] = Coordinate::columnIndexFromString($leftMostColumn) - 1;
|
||||
} else {
|
||||
// thaw panes
|
||||
return;
|
||||
|
|
|
@ -244,31 +244,31 @@ class Worksheet extends WriterPart
|
|||
|
||||
// Pane
|
||||
$pane = '';
|
||||
$topLeftCell = $pSheet->getFreezePane();
|
||||
if (($topLeftCell != '') && ($topLeftCell != 'A1')) {
|
||||
$activeCell = $topLeftCell;
|
||||
// Calculate freeze coordinates
|
||||
$xSplit = $ySplit = 0;
|
||||
|
||||
list($xSplit, $ySplit) = Coordinate::coordinateFromString($topLeftCell);
|
||||
if ($pSheet->getFreezePane()) {
|
||||
list($xSplit, $ySplit) = Coordinate::coordinateFromString($pSheet->getFreezePane());
|
||||
$xSplit = Coordinate::columnIndexFromString($xSplit);
|
||||
--$xSplit;
|
||||
--$ySplit;
|
||||
|
||||
$topLeftCell = $pSheet->getTopLeftCell();
|
||||
$activeCell = $topLeftCell;
|
||||
|
||||
// pane
|
||||
$pane = 'topRight';
|
||||
$objWriter->startElement('pane');
|
||||
if ($xSplit > 1) {
|
||||
$objWriter->writeAttribute('xSplit', $xSplit - 1);
|
||||
if ($xSplit > 0) {
|
||||
$objWriter->writeAttribute('xSplit', $xSplit);
|
||||
}
|
||||
if ($ySplit > 1) {
|
||||
$objWriter->writeAttribute('ySplit', $ySplit - 1);
|
||||
$pane = ($xSplit > 1) ? 'bottomRight' : 'bottomLeft';
|
||||
if ($ySplit > 0) {
|
||||
$objWriter->writeAttribute('ySplit', $ySplit);
|
||||
$pane = ($xSplit > 0) ? 'bottomRight' : 'bottomLeft';
|
||||
}
|
||||
$objWriter->writeAttribute('topLeftCell', $topLeftCell);
|
||||
$objWriter->writeAttribute('activePane', $pane);
|
||||
$objWriter->writeAttribute('state', 'frozen');
|
||||
$objWriter->endElement();
|
||||
|
||||
if (($xSplit > 1) && ($ySplit > 1)) {
|
||||
if (($xSplit > 0) && ($ySplit > 0)) {
|
||||
// Write additional selections if more than two panes (ie both an X and a Y split)
|
||||
$objWriter->startElement('selection');
|
||||
$objWriter->writeAttribute('pane', 'topRight');
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xls as ReaderXls;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xls as WriterXls;
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
class XlsTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testFreezePane()
|
||||
{
|
||||
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet');
|
||||
|
||||
$cellSplit = 'B2';
|
||||
$topLeftCell = 'E5';
|
||||
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$active = $spreadsheet->getActiveSheet();
|
||||
$active->freezePane($cellSplit, $topLeftCell);
|
||||
|
||||
$writer = new WriterXls($spreadsheet);
|
||||
$writer->save($filename);
|
||||
|
||||
// Read written file
|
||||
$reader = new ReaderXls();
|
||||
$reloadedSpreadsheet = $reader->load($filename);
|
||||
$reloadedActive = $reloadedSpreadsheet->getActiveSheet();
|
||||
$actualCellSplit = $reloadedActive->getFreezePane();
|
||||
$actualTopLeftCell = $reloadedActive->getTopLeftCell();
|
||||
|
||||
self::assertSame($cellSplit, $actualCellSplit, 'should be able to set freeze pane');
|
||||
self::assertSame($topLeftCell, $actualTopLeftCell, 'should be able to set the top left cell');
|
||||
}
|
||||
}
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Reader;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as ReaderXlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as WriterXlsx;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class XlsxTest extends TestCase
|
||||
|
@ -13,7 +16,32 @@ class XlsxTest extends TestCase
|
|||
public function testLoadXlsxWithoutCellReference()
|
||||
{
|
||||
$filename = './data/Reader/XLSX/without_cell_reference.xlsx';
|
||||
$reader = new Xlsx();
|
||||
$reader = new ReaderXlsx();
|
||||
$reader->load($filename);
|
||||
}
|
||||
|
||||
public function testFreezePane()
|
||||
{
|
||||
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet');
|
||||
|
||||
$cellSplit = 'B2';
|
||||
$topLeftCell = 'E5';
|
||||
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$active = $spreadsheet->getActiveSheet();
|
||||
$active->freezePane($cellSplit, $topLeftCell);
|
||||
|
||||
$writer = new WriterXlsx($spreadsheet);
|
||||
$writer->save($filename);
|
||||
|
||||
// Read written file
|
||||
$reader = new ReaderXlsx();
|
||||
$reloadedSpreadsheet = $reader->load($filename);
|
||||
$reloadedActive = $reloadedSpreadsheet->getActiveSheet();
|
||||
$actualCellSplit = $reloadedActive->getFreezePane();
|
||||
$actualTopLeftCell = $reloadedActive->getTopLeftCell();
|
||||
|
||||
self::assertSame($cellSplit, $actualCellSplit, 'should be able to set freeze pane');
|
||||
self::assertSame($topLeftCell, $actualTopLeftCell, 'should be able to set the top left cell');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue