parent
4e0344c3af
commit
49775bd972
|
@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
- Freeze Panes takes wrong coordinates for XLSX - [#322](https://github.com/PHPOffice/PhpSpreadsheet/issues/322)
|
- Freeze Panes takes wrong coordinates for XLSX - [#322](https://github.com/PHPOffice/PhpSpreadsheet/issues/322)
|
||||||
- `COLUMNS` and `ROWS` functions crashed in some cases - [#336](https://github.com/PHPOffice/PhpSpreadsheet/issues/336)
|
- `COLUMNS` and `ROWS` functions crashed in some cases - [#336](https://github.com/PHPOffice/PhpSpreadsheet/issues/336)
|
||||||
- Support XML file without styles - [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331)
|
- Support XML file without styles - [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331)
|
||||||
|
- Cell coordinates which are already a range cause an exception [#319](https://github.com/PHPOffice/PhpSpreadsheet/issues/319)
|
||||||
|
|
||||||
## [1.0.0] - 2017-12-25
|
## [1.0.0] - 2017-12-25
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ abstract class Coordinate
|
||||||
{
|
{
|
||||||
if (preg_match("/^([$]?[A-Z]{1,3})([$]?\d{1,7})$/", $pCoordinateString, $matches)) {
|
if (preg_match("/^([$]?[A-Z]{1,3})([$]?\d{1,7})$/", $pCoordinateString, $matches)) {
|
||||||
return [$matches[1], $matches[2]];
|
return [$matches[1], $matches[2]];
|
||||||
} elseif ((strpos($pCoordinateString, ':') !== false) || (strpos($pCoordinateString, ',') !== false)) {
|
} elseif (self::coordinateIsRange($pCoordinateString)) {
|
||||||
throw new Exception('Cell coordinate string can not be a range of cells');
|
throw new Exception('Cell coordinate string can not be a range of cells');
|
||||||
} elseif ($pCoordinateString == '') {
|
} elseif ($pCoordinateString == '') {
|
||||||
throw new Exception('Cell coordinate can not be zero-length string');
|
throw new Exception('Cell coordinate can not be zero-length string');
|
||||||
|
@ -41,6 +41,18 @@ abstract class Coordinate
|
||||||
throw new Exception('Invalid cell coordinate ' . $pCoordinateString);
|
throw new Exception('Invalid cell coordinate ' . $pCoordinateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a coordinate represents a range of cells.
|
||||||
|
*
|
||||||
|
* @param string $coord eg: 'A1' or 'A1:A2' or 'A1:A2,C1:C2'
|
||||||
|
*
|
||||||
|
* @return bool Whether the coordinate represents a range of cells
|
||||||
|
*/
|
||||||
|
public static function coordinateIsRange($coord)
|
||||||
|
{
|
||||||
|
return (strpos($coord, ':') !== false) || (strpos($coord, ',') !== false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make string row, column or cell coordinate absolute.
|
* Make string row, column or cell coordinate absolute.
|
||||||
*
|
*
|
||||||
|
@ -53,7 +65,10 @@ abstract class Coordinate
|
||||||
*/
|
*/
|
||||||
public static function absoluteReference($pCoordinateString)
|
public static function absoluteReference($pCoordinateString)
|
||||||
{
|
{
|
||||||
if (strpos($pCoordinateString, ':') === false && strpos($pCoordinateString, ',') === false) {
|
if (self::coordinateIsRange($pCoordinateString)) {
|
||||||
|
throw new Exception('Cell coordinate string can not be a range of cells');
|
||||||
|
}
|
||||||
|
|
||||||
// Split out any worksheet name from the reference
|
// Split out any worksheet name from the reference
|
||||||
$worksheet = '';
|
$worksheet = '';
|
||||||
$cellAddress = explode('!', $pCoordinateString);
|
$cellAddress = explode('!', $pCoordinateString);
|
||||||
|
@ -74,9 +89,6 @@ abstract class Coordinate
|
||||||
return $worksheet . self::absoluteCoordinate($pCoordinateString);
|
return $worksheet . self::absoluteCoordinate($pCoordinateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Cell coordinate string can not be a range of cells');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make string coordinate absolute.
|
* Make string coordinate absolute.
|
||||||
*
|
*
|
||||||
|
@ -88,7 +100,10 @@ abstract class Coordinate
|
||||||
*/
|
*/
|
||||||
public static function absoluteCoordinate($pCoordinateString)
|
public static function absoluteCoordinate($pCoordinateString)
|
||||||
{
|
{
|
||||||
if (strpos($pCoordinateString, ':') === false && strpos($pCoordinateString, ',') === false) {
|
if (self::coordinateIsRange($pCoordinateString)) {
|
||||||
|
throw new Exception('Cell coordinate string can not be a range of cells');
|
||||||
|
}
|
||||||
|
|
||||||
// Split out any worksheet name from the coordinate
|
// Split out any worksheet name from the coordinate
|
||||||
$worksheet = '';
|
$worksheet = '';
|
||||||
$cellAddress = explode('!', $pCoordinateString);
|
$cellAddress = explode('!', $pCoordinateString);
|
||||||
|
@ -107,9 +122,6 @@ abstract class Coordinate
|
||||||
return $worksheet . '$' . $column . '$' . $row;
|
return $worksheet . '$' . $column . '$' . $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Cell coordinate string can not be a range of cells');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split range into coordinate strings.
|
* Split range into coordinate strings.
|
||||||
*
|
*
|
||||||
|
@ -330,7 +342,7 @@ abstract class Coordinate
|
||||||
$cellBlocks = explode(' ', str_replace('$', '', strtoupper($pRange)));
|
$cellBlocks = explode(' ', str_replace('$', '', strtoupper($pRange)));
|
||||||
foreach ($cellBlocks as $cellBlock) {
|
foreach ($cellBlocks as $cellBlock) {
|
||||||
// Single cell?
|
// Single cell?
|
||||||
if (strpos($cellBlock, ':') === false && strpos($cellBlock, ',') === false) {
|
if (!self::coordinateIsRange($cellBlock)) {
|
||||||
$returnValue[] = $cellBlock;
|
$returnValue[] = $cellBlock;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -400,8 +412,15 @@ abstract class Coordinate
|
||||||
public static function mergeRangesInCollection(array $pCoordCollection)
|
public static function mergeRangesInCollection(array $pCoordCollection)
|
||||||
{
|
{
|
||||||
$hashedValues = [];
|
$hashedValues = [];
|
||||||
|
$mergedCoordCollection = [];
|
||||||
|
|
||||||
foreach ($pCoordCollection as $coord => $value) {
|
foreach ($pCoordCollection as $coord => $value) {
|
||||||
|
if (self::coordinateIsRange($coord)) {
|
||||||
|
$mergedCoordCollection[$coord] = $value;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
list($column, $row) = self::coordinateFromString($coord);
|
list($column, $row) = self::coordinateFromString($coord);
|
||||||
$row = (int) (ltrim($row, '$'));
|
$row = (int) (ltrim($row, '$'));
|
||||||
$hashCode = $column . '-' . (is_object($value) ? $value->getHashCode() : $value);
|
$hashCode = $column . '-' . (is_object($value) ? $value->getHashCode() : $value);
|
||||||
|
@ -417,7 +436,6 @@ abstract class Coordinate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$mergedCoordCollection = [];
|
|
||||||
ksort($hashedValues);
|
ksort($hashedValues);
|
||||||
|
|
||||||
foreach ($hashedValues as $hashedValue) {
|
foreach ($hashedValues as $hashedValue) {
|
||||||
|
|
|
@ -760,7 +760,7 @@ class ReferenceHelper
|
||||||
* Update cell reference.
|
* Update cell reference.
|
||||||
*
|
*
|
||||||
* @param string $pCellRange Cell range
|
* @param string $pCellRange Cell range
|
||||||
* @param int $pBefore Insert before this one
|
* @param string $pBefore Insert before this one
|
||||||
* @param int $pNumCols Number of columns to increment
|
* @param int $pNumCols Number of columns to increment
|
||||||
* @param int $pNumRows Number of rows to increment
|
* @param int $pNumRows Number of rows to increment
|
||||||
*
|
*
|
||||||
|
@ -774,13 +774,14 @@ class ReferenceHelper
|
||||||
if (strpos($pCellRange, '!') !== false) {
|
if (strpos($pCellRange, '!') !== false) {
|
||||||
return $pCellRange;
|
return $pCellRange;
|
||||||
// Is it a range or a single cell?
|
// Is it a range or a single cell?
|
||||||
} elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) {
|
} elseif (!Coordinate::coordinateIsRange($pCellRange)) {
|
||||||
// Single cell
|
// Single cell
|
||||||
return $this->updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
return $this->updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
||||||
} elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) {
|
} elseif (Coordinate::coordinateIsRange($pCellRange)) {
|
||||||
// Range
|
// Range
|
||||||
return $this->updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
return $this->updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return original
|
// Return original
|
||||||
return $pCellRange;
|
return $pCellRange;
|
||||||
}
|
}
|
||||||
|
@ -817,7 +818,7 @@ class ReferenceHelper
|
||||||
* Update cell range.
|
* Update cell range.
|
||||||
*
|
*
|
||||||
* @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3')
|
* @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3')
|
||||||
* @param int $pBefore Insert before this one
|
* @param string $pBefore Insert before this one
|
||||||
* @param int $pNumCols Number of columns to increment
|
* @param int $pNumCols Number of columns to increment
|
||||||
* @param int $pNumRows Number of rows to increment
|
* @param int $pNumRows Number of rows to increment
|
||||||
*
|
*
|
||||||
|
@ -827,7 +828,10 @@ class ReferenceHelper
|
||||||
*/
|
*/
|
||||||
private function updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0)
|
private function updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0)
|
||||||
{
|
{
|
||||||
if (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) {
|
if (!Coordinate::coordinateIsRange($pCellRange)) {
|
||||||
|
throw new Exception('Only cell ranges may be passed to this method.');
|
||||||
|
}
|
||||||
|
|
||||||
// Update range
|
// Update range
|
||||||
$range = Coordinate::splitRange($pCellRange);
|
$range = Coordinate::splitRange($pCellRange);
|
||||||
$ic = count($range);
|
$ic = count($range);
|
||||||
|
@ -850,14 +854,11 @@ class ReferenceHelper
|
||||||
return Coordinate::buildRange($range);
|
return Coordinate::buildRange($range);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Only cell ranges may be passed to this method.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update single cell reference.
|
* Update single cell reference.
|
||||||
*
|
*
|
||||||
* @param string $pCellReference Single cell reference
|
* @param string $pCellReference Single cell reference
|
||||||
* @param int $pBefore Insert before this one
|
* @param string $pBefore Insert before this one
|
||||||
* @param int $pNumCols Number of columns to increment
|
* @param int $pNumCols Number of columns to increment
|
||||||
* @param int $pNumRows Number of rows to increment
|
* @param int $pNumRows Number of rows to increment
|
||||||
*
|
*
|
||||||
|
@ -867,7 +868,10 @@ class ReferenceHelper
|
||||||
*/
|
*/
|
||||||
private function updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0)
|
private function updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0)
|
||||||
{
|
{
|
||||||
if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) {
|
if (Coordinate::coordinateIsRange($pCellReference)) {
|
||||||
|
throw new Exception('Only single cell references may be passed to this method.');
|
||||||
|
}
|
||||||
|
|
||||||
// Get coordinate of $pBefore
|
// Get coordinate of $pBefore
|
||||||
list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore);
|
list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore);
|
||||||
|
|
||||||
|
@ -892,9 +896,6 @@ class ReferenceHelper
|
||||||
return $newColumn . $newRow;
|
return $newColumn . $newRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Only single cell references may be passed to this method.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __clone implementation. Cloning should not be allowed in a Singleton!
|
* __clone implementation. Cloning should not be allowed in a Singleton!
|
||||||
*
|
*
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ class Worksheet implements IComparable
|
||||||
// Uppercase coordinate
|
// Uppercase coordinate
|
||||||
$pCoordinate = strtoupper($pCoordinate);
|
$pCoordinate = strtoupper($pCoordinate);
|
||||||
|
|
||||||
if (strpos($pCoordinate, ':') !== false || strpos($pCoordinate, ',') !== false) {
|
if (Coordinate::coordinateIsRange($pCoordinate)) {
|
||||||
throw new Exception('Cell coordinate can not be a range of cells.');
|
throw new Exception('Cell coordinate can not be a range of cells.');
|
||||||
} elseif (strpos($pCoordinate, '$') !== false) {
|
} elseif (strpos($pCoordinate, '$') !== false) {
|
||||||
throw new Exception('Cell coordinate must not be absolute.');
|
throw new Exception('Cell coordinate must not be absolute.');
|
||||||
|
@ -1324,7 +1324,7 @@ class Worksheet implements IComparable
|
||||||
// Uppercase coordinate
|
// Uppercase coordinate
|
||||||
$pCoordinate = strtoupper($pCoordinate);
|
$pCoordinate = strtoupper($pCoordinate);
|
||||||
|
|
||||||
if (strpos($pCoordinate, ':') !== false || strpos($pCoordinate, ',') !== false) {
|
if (Coordinate::coordinateIsRange($pCoordinate)) {
|
||||||
throw new Exception('Cell coordinate can not be a range of cells.');
|
throw new Exception('Cell coordinate can not be a range of cells.');
|
||||||
} elseif (strpos($pCoordinate, '$') !== false) {
|
} elseif (strpos($pCoordinate, '$') !== false) {
|
||||||
throw new Exception('Cell coordinate must not be absolute.');
|
throw new Exception('Cell coordinate must not be absolute.');
|
||||||
|
@ -1993,7 +1993,7 @@ class Worksheet implements IComparable
|
||||||
*/
|
*/
|
||||||
public function freezePane($cell, $topLeftCell = null)
|
public function freezePane($cell, $topLeftCell = null)
|
||||||
{
|
{
|
||||||
if (is_string($cell) && (strpos($cell, ':') !== false || strpos($cell, ',') !== false)) {
|
if (is_string($cell) && Coordinate::coordinateIsRange($cell)) {
|
||||||
throw new Exception('Freeze pane can not be set on a range of cells.');
|
throw new Exception('Freeze pane can not be set on a range of cells.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2337,7 +2337,7 @@ class Worksheet implements IComparable
|
||||||
// Uppercase coordinate
|
// Uppercase coordinate
|
||||||
$pCellCoordinate = strtoupper($pCellCoordinate);
|
$pCellCoordinate = strtoupper($pCellCoordinate);
|
||||||
|
|
||||||
if (strpos($pCellCoordinate, ':') !== false || strpos($pCellCoordinate, ',') !== false) {
|
if (Coordinate::coordinateIsRange($pCellCoordinate)) {
|
||||||
throw new Exception('Cell coordinate string can not be a range of cells.');
|
throw new Exception('Cell coordinate string can not be a range of cells.');
|
||||||
} elseif (strpos($pCellCoordinate, '$') !== false) {
|
} elseif (strpos($pCellCoordinate, '$') !== false) {
|
||||||
throw new Exception('Cell coordinate string must not be absolute.');
|
throw new Exception('Cell coordinate string must not be absolute.');
|
||||||
|
@ -2428,7 +2428,7 @@ class Worksheet implements IComparable
|
||||||
// Convert '1:3' to 'A1:XFD3'
|
// Convert '1:3' to 'A1:XFD3'
|
||||||
$pCoordinate = preg_replace('/^(\d+):(\d+)$/', 'A${1}:XFD${2}', $pCoordinate);
|
$pCoordinate = preg_replace('/^(\d+):(\d+)$/', 'A${1}:XFD${2}', $pCoordinate);
|
||||||
|
|
||||||
if (strpos($pCoordinate, ':') !== false || strpos($pCoordinate, ',') !== false) {
|
if (Coordinate::coordinateIsRange($pCoordinate)) {
|
||||||
list($first) = Coordinate::splitRange($pCoordinate);
|
list($first) = Coordinate::splitRange($pCoordinate);
|
||||||
$this->activeCell = $first[0];
|
$this->activeCell = $first[0];
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -331,4 +331,20 @@ class CoordinateTest extends TestCase
|
||||||
{
|
{
|
||||||
return require 'data/CellMergeRangesInCollection.php';
|
return require 'data/CellMergeRangesInCollection.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCoordinateIsRange
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
*/
|
||||||
|
public function testCoordinateIsRange($expectedResult, ...$args)
|
||||||
|
{
|
||||||
|
$result = Coordinate::coordinateIsRange(...$args);
|
||||||
|
self::assertEquals($expectedResult, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerCoordinateIsRange()
|
||||||
|
{
|
||||||
|
return require 'data/CoordinateIsRange.php';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,4 +55,16 @@ return [
|
||||||
'A3' => 'z',
|
'A3' => 'z',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
'C1' => 'x',
|
||||||
|
'A1:A3' => 'x',
|
||||||
|
'A1:A3,C1:C3' => 'y',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'C1' => 'x',
|
||||||
|
'A1:A3' => 'x',
|
||||||
|
'A1:A3,C1:C3' => 'y',
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
false,
|
||||||
|
'A1',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
false,
|
||||||
|
'$A$1',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
true,
|
||||||
|
'A1,C3',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
true,
|
||||||
|
'A1:A10',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
true,
|
||||||
|
'A1:A10,C4',
|
||||||
|
],
|
||||||
|
];
|
Loading…
Reference in New Issue