PHPStan Level 2

This commit is contained in:
Adrien Crivelli 2021-04-03 17:42:11 +09:00
parent 42761f90b7
commit d02352845c
No known key found for this signature in database
GPG Key ID: 16D79B903B4B5874
90 changed files with 778 additions and 591 deletions

View File

@ -160,7 +160,7 @@ return PhpCsFixer\Config::create()
'php_unit_test_annotation' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_add_missing_param_annotation' => false, // Don't add things that bring no value
'phpdoc_align' => false, // Waste of time
'phpdoc_annotation_without_dot' => true,
'phpdoc_indent' => true,

View File

@ -1,11 +1,16 @@
parameters:
level: 1
level: 2
paths:
- src/
- tests/
ignoreErrors:
- '~^Class GdImage not found\.$~'
- '~^Return typehint of method .* has invalid type GdImage\.$~'
- '~^Property .* has unknown class GdImage as its type\.$~'
- '~^Parameter .* of method .* has invalid typehint type GdImage\.$~'
# Ignore all JpGraph issues
- '~^Constant (MARK_CIRCLE|MARK_CROSS|MARK_DIAMOND|MARK_DTRIANGLE|MARK_FILLEDCIRCLE|MARK_SQUARE|MARK_STAR|MARK_UTRIANGLE|MARK_X|SIDE_RIGHT) not found\.$~'
- '~^Instantiated class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot) not found\.$~'
- '~^Call to method .*\(\) on an unknown class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot)\.$~'
- '~^Access to property .* on an unknown class (AccBarPlot|AccLinePlot|BarPlot|ContourPlot|Graph|GroupBarPlot|GroupBarPlot|LinePlot|LinePlot|PieGraph|PiePlot|PiePlot3D|PiePlotC|RadarGraph|RadarPlot|ScatterPlot|Spline|StockPlot)\.$~'

View File

@ -198,7 +198,7 @@ class DateTime
* @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
* depending on the value of the ReturnDateType flag
*/
public static function DATEVALUE($dateValue = 1)
public static function DATEVALUE($dateValue)
{
return DateTimeExcel\DateValue::funcDateValue($dateValue);
}

View File

@ -89,7 +89,7 @@ class DateDif
private static function datedifM(DateInterval $PHPDiffDateObject): int
{
return (int) 12 * $PHPDiffDateObject->format('%y') + $PHPDiffDateObject->format('%m');
return 12 * (int) $PHPDiffDateObject->format('%y') + (int) $PHPDiffDateObject->format('%m');
}
private static function datedifMD(int $startDays, int $endDays, DateTime $PHPEndDateObject, DateInterval $PHPDiffDateObject): int

View File

@ -33,7 +33,7 @@ class DateValue
* @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
* depending on the value of the ReturnDateType flag
*/
public static function funcDateValue($dateValue = 1)
public static function funcDateValue($dateValue)
{
$dti = new DateTimeImmutable();
$baseYear = Date::getExcelCalendar();

View File

@ -19,20 +19,20 @@ class Days360
* DAYS360(startDate,endDate[,method])
*
* @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
* PHP DateTime object, or a standard date string
* PHP DateTime object, or a standard date string
* @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
* PHP DateTime object, or a standard date string
* PHP DateTime object, or a standard date string
* @param mixed $method US or European Method as a bool
* FALSE or omitted: U.S. (NASD) method. If the starting date is
* the last day of a month, it becomes equal to the 30th of the
* same month. If the ending date is the last day of a month and
* the starting date is earlier than the 30th of a month, the
* ending date becomes equal to the 1st of the next month;
* otherwise the ending date becomes equal to the 30th of the
* same month.
* TRUE: European method. Starting dates and ending dates that
* occur on the 31st of a month become equal to the 30th of the
* same month.
* FALSE or omitted: U.S. (NASD) method. If the starting date is
* the last day of a month, it becomes equal to the 30th of the
* same month. If the ending date is the last day of a month and
* the starting date is earlier than the 30th of a month, the
* ending date becomes equal to the 1st of the next month;
* otherwise the ending date becomes equal to the 30th of the
* same month.
* TRUE: European method. Starting dates and ending dates that
* occur on the 31st of a month become equal to the 30th of the
* same month.
*
* @return int|string Number of days between start date and end date
*/

View File

@ -67,9 +67,9 @@ class WeekNum
return 0;
}
Helpers::silly1900($PHPDateObject, '+ 5 years'); // 1905 calendar matches
$dayOfYear = $PHPDateObject->format('z');
$dayOfYear = (int) $PHPDateObject->format('z');
$PHPDateObject->modify('-' . $dayOfYear . ' days');
$firstDayOfFirstWeek = $PHPDateObject->format('w');
$firstDayOfFirstWeek = (int) $PHPDateObject->format('w');
$daysInFirstWeek = (6 - $firstDayOfFirstWeek + $method) % 7;
$daysInFirstWeek += 7 * !$daysInFirstWeek;
$endFirstWeek = $daysInFirstWeek - 1;

View File

@ -129,6 +129,7 @@ class WorkDay
$startDoW = WeekDay::funcWeekDay($startDate, 3);
if (WeekDay::funcWeekDay($startDate, 3) >= 5) {
// @phpstan-ignore-next-line
$startDate += -$startDoW + 4;
++$endDays;
}
@ -173,6 +174,7 @@ class WorkDay
// Adjust the calculated end date if it falls over a weekend
$endDoW = WeekDay::funcWeekDay($endDate, 3);
if ($endDoW >= 5) {
// @phpstan-ignore-next-line
$endDate += -$endDoW + 4;
}
}

View File

@ -22,11 +22,11 @@ class BesselI
* This code provides a more accurate calculation
*
* @param mixed $x A float value at which to evaluate the function.
* If x is nonnumeric, BESSELI returns the #VALUE! error value.
* If x is nonnumeric, BESSELI returns the #VALUE! error value.
* @param mixed $ord The integer order of the Bessel function.
* If ord is not an integer, it is truncated.
* If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
* If $ord < 0, BESSELI returns the #NUM! error value.
* If ord is not an integer, it is truncated.
* If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
* If $ord < 0, BESSELI returns the #NUM! error value.
*
* @return float|string Result, or a string containing an error
*/

View File

@ -21,11 +21,11 @@ class BesselJ
* values with x < -8 and x > 8. This code provides a more accurate calculation
*
* @param mixed $x A float value at which to evaluate the function.
* If x is nonnumeric, BESSELJ returns the #VALUE! error value.
* If x is nonnumeric, BESSELJ returns the #VALUE! error value.
* @param mixed $ord The integer order of the Bessel function.
* If ord is not an integer, it is truncated.
* If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
* If $ord < 0, BESSELJ returns the #NUM! error value.
* If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
* If $ord < 0, BESSELJ returns the #NUM! error value.
*
* @return float|string Result, or a string containing an error
*/

View File

@ -19,10 +19,10 @@ class BesselK
* BESSELK(x,ord)
*
* @param mixed $x A float value at which to evaluate the function.
* If x is nonnumeric, BESSELK returns the #VALUE! error value.
* If x is nonnumeric, BESSELK returns the #VALUE! error value.
* @param mixed $ord The integer order of the Bessel function.
* If ord is not an integer, it is truncated.
* If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
* If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
* If $ord < 0, BESSELKI returns the #NUM! error value.
*
* @return float|string Result, or a string containing an error

View File

@ -198,6 +198,7 @@ class NonPeriodic
return $e->getMessage();
}
if ($date0 > $datei) {
/** @phpstan-ignore-next-line */
$dif = $ordered ? Functions::NAN() : -DateTimeExcel\DateDif::funcDateDif($datei, $date0, 'd');
} else {
$dif = DateTimeExcel\DateDif::funcDateDif($date0, $datei, 'd');

View File

@ -576,7 +576,7 @@ class Functions
/**
* Convert a multi-dimensional array to a simple 1-dimensional array.
*
* @param mixed (array) $array Array to be flattened
* @param array|mixed $array Array to be flattened
*
* @return array Flattened array
*/
@ -609,7 +609,7 @@ class Functions
/**
* Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing.
*
* @param mixed (array) $array Array to be flattened
* @param array|mixed $array Array to be flattened
*
* @return array Flattened array
*/

View File

@ -9,7 +9,7 @@ class Matrix
/**
* TRANSPOSE.
*
* @param mixed (array) $matrixData A matrix of values
* @param array|mixed $matrixData A matrix of values
*
* @return array
*/

View File

@ -27,7 +27,7 @@ class AddressHelper
}
// Bracketed R references are relative to the current row
if ($rowReference[0] === '[') {
$rowReference = $currentRowNumber + trim($rowReference, '[]');
$rowReference = $currentRowNumber + (int) trim($rowReference, '[]');
}
$columnReference = $cellReference[4];
// Empty C reference is the current column
@ -36,7 +36,7 @@ class AddressHelper
}
// Bracketed C references are relative to the current column
if (is_string($columnReference) && $columnReference[0] === '[') {
$columnReference = $currentColumnNumber + trim($columnReference, '[]');
$columnReference = $currentColumnNumber + (int) trim($columnReference, '[]');
}
if ($columnReference <= 0 || $rowReference <= 0) {

View File

@ -25,7 +25,7 @@ abstract class Coordinate
*
* @param string $pCoordinateString eg: 'A1'
*
* @return string[] Array containing column and row (indexes 0 and 1)
* @return array{0: string, 1: string} Array containing column and row (indexes 0 and 1)
*/
public static function coordinateFromString($pCoordinateString)
{
@ -40,6 +40,23 @@ abstract class Coordinate
throw new Exception('Invalid cell coordinate ' . $pCoordinateString);
}
/**
* Get indexes from a string coordinates.
*
* @param string $coordinates eg: 'A1', '$B$12'
*
* @return array{0: int, 1: int} Array containing column index and row index (indexes 0 and 1)
*/
public static function indexesFromString(string $coordinates): array
{
[$col, $row] = self::coordinateFromString($coordinates);
return [
self::columnIndexFromString(ltrim($col, '$')),
(int) ltrim($row, '$'),
];
}
/**
* Checks if a coordinate represents a range of cells.
*

View File

@ -135,10 +135,8 @@ class Axis extends Properties
* Get Series Data Type.
*
* @param mixed $format_code
*
* @return string
*/
public function setAxisNumberProperties($format_code)
public function setAxisNumberProperties($format_code): void
{
$this->axisNumber['format'] = (string) $format_code;
$this->axisNumber['source_linked'] = 0;
@ -367,7 +365,7 @@ class Axis extends Properties
/**
* Set Shadow Properties from Mapped Values.
*
* @param mixed &$reference
* @param mixed $reference
*
* @return $this
*/

View File

@ -424,7 +424,7 @@ class Chart
/**
* Get the top left position of the chart.
*
* @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell
* @return array{cell: string, xOffset: int, yOffset: int} an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell
*/
public function getTopLeftPosition()
{

View File

@ -318,7 +318,7 @@ class GridLines extends Properties
/**
* Set Shadow Properties Values.
*
* @param mixed &$reference
* @param mixed $reference
*
* @return $this
*/

View File

@ -43,10 +43,8 @@ class PlotArea
/**
* Get Number of Plot Groups.
*
* @return array of DataSeries
*/
public function getPlotGroupCount()
public function getPlotGroupCount(): int
{
return count($this->plotSeries);
}

View File

@ -392,13 +392,11 @@ class Properties
/**
* Get a Custom Property Type.
*
* @return string
* @return null|string
*/
public function getCustomPropertyType(string $propertyName)
{
if (isset($this->customProperties[$propertyName])) {
return $this->customProperties[$propertyName]['type'];
}
return $this->customProperties[$propertyName]['type'] ?? null;
}
private function identifyPropertyType($propertyValue)

View File

@ -2,12 +2,15 @@
namespace PhpOffice\PhpSpreadsheet;
/**
* @template T of IComparable
*/
class HashTable
{
/**
* HashTable elements.
*
* @var IComparable[]
* @var T[]
*/
protected $items = [];
@ -21,7 +24,7 @@ class HashTable
/**
* Create a new \PhpOffice\PhpSpreadsheet\HashTable.
*
* @param IComparable[] $pSource Optional source array to create HashTable from
* @param T[] $pSource Optional source array to create HashTable from
*/
public function __construct($pSource = null)
{
@ -34,7 +37,7 @@ class HashTable
/**
* Add HashTable items from source.
*
* @param IComparable[] $pSource Source array to create HashTable from
* @param T[] $pSource Source array to create HashTable from
*/
public function addFromSource(?array $pSource = null): void
{
@ -51,7 +54,7 @@ class HashTable
/**
* Add HashTable item.
*
* @param IComparable $pSource Item to add
* @param T $pSource Item to add
*/
public function add(IComparable $pSource): void
{
@ -65,7 +68,7 @@ class HashTable
/**
* Remove HashTable item.
*
* @param IComparable $pSource Item to remove
* @param T $pSource Item to remove
*/
public function remove(IComparable $pSource): void
{
@ -123,7 +126,7 @@ class HashTable
*
* @param int $pIndex
*
* @return IComparable
* @return T
*/
public function getByIndex($pIndex)
{
@ -139,7 +142,7 @@ class HashTable
*
* @param string $pHashCode
*
* @return IComparable
* @return T
*/
public function getByHashCode($pHashCode)
{
@ -153,7 +156,7 @@ class HashTable
/**
* HashTable to array.
*
* @return IComparable[]
* @return T[]
*/
public function toArray()
{

View File

@ -657,7 +657,7 @@ class Gnumeric extends BaseReader
$column = $columnAttributes['No'];
$columnWidth = ((float) $columnAttributes['Unit']) / 5.4;
$hidden = (isset($columnAttributes['Hidden'])) && ((string) $columnAttributes['Hidden'] == '1');
$columnCount = $columnAttributes['Count'] ?? 1;
$columnCount = (int) ($columnAttributes['Count'] ?? 1);
while ($c < $column) {
$this->spreadsheet->getActiveSheet()->getColumnDimension(Coordinate::stringFromColumnIndex($c + 1))->setWidth($defaultWidth);
++$c;
@ -696,7 +696,7 @@ class Gnumeric extends BaseReader
$row = $rowAttributes['No'];
$rowHeight = (float) $rowAttributes['Unit'];
$hidden = (isset($rowAttributes['Hidden'])) && ((string) $rowAttributes['Hidden'] == '1');
$rowCount = $rowAttributes['Count'] ?? 1;
$rowCount = (int) ($rowAttributes['Count'] ?? 1);
while ($r < $row) {
++$r;
$this->spreadsheet->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight);

View File

@ -910,8 +910,6 @@ class Html extends BaseReader
/**
* Check if has #, so we can get clean hex.
*
* @param $value
*
* @return null|string
*/
public function getStyleColor($value)

View File

@ -380,9 +380,8 @@ class Ods extends BaseReader
}
$columnID = 'A';
foreach ($childNode->childNodes as $key => $cellData) {
// @var \DOMElement $cellData
/** @var DOMElement $cellData */
foreach ($childNode->childNodes as $cellData) {
if ($this->getReadFilter() !== null) {
if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) {
++$columnID;
@ -672,8 +671,9 @@ class Ods extends BaseReader
$this->lookForSelectedCells($settings, $spreadsheet, $configNs);
}
private function lookForActiveSheet(DOMNode $settings, Spreadsheet $spreadsheet, string $configNs): void
private function lookForActiveSheet(DOMElement $settings, Spreadsheet $spreadsheet, string $configNs): void
{
/** @var DOMElement $t */
foreach ($settings->getElementsByTagNameNS($configNs, 'config-item') as $t) {
if ($t->getAttributeNs($configNs, 'name') === 'ActiveTable') {
try {
@ -687,8 +687,9 @@ class Ods extends BaseReader
}
}
private function lookForSelectedCells(DOMNode $settings, Spreadsheet $spreadsheet, string $configNs): void
private function lookForSelectedCells(DOMElement $settings, Spreadsheet $spreadsheet, string $configNs): void
{
/** @var DOMElement $t */
foreach ($settings->getElementsByTagNameNS($configNs, 'config-item-map-named') as $t) {
if ($t->getAttributeNs($configNs, 'name') === 'Tables') {
foreach ($t->getElementsByTagNameNS($configNs, 'config-item-map-entry') as $ws) {

View File

@ -169,7 +169,7 @@ class Slk extends BaseReader
foreach ($rowData as $rowDatum) {
switch ($rowDatum[0]) {
case 'X':
$columnIndex = substr($rowDatum, 1) - 1;
$columnIndex = (int) substr($rowDatum, 1) - 1;
break;
case 'Y':
@ -251,7 +251,7 @@ class Slk extends BaseReader
}
// Bracketed R references are relative to the current row
if ($rowReference[0] == '[') {
$rowReference = $row + trim($rowReference, '[]');
$rowReference = (int) $row + (int) trim($rowReference, '[]');
}
$columnReference = $cellReference[4][0];
// Empty C reference is the current column
@ -260,7 +260,7 @@ class Slk extends BaseReader
}
// Bracketed C references are relative to the current column
if ($columnReference[0] == '[') {
$columnReference = $column + trim($columnReference, '[]');
$columnReference = (int) $column + (int) trim($columnReference, '[]');
}
$A1CellReference = Coordinate::stringFromColumnIndex($columnReference) . $rowReference;

View File

@ -224,7 +224,7 @@ class Xls extends BaseReader
/**
* Shared fonts.
*
* @var array
* @var Font[]
*/
private $objFonts;
@ -1293,7 +1293,7 @@ class Xls extends BaseReader
}
}
// Named Value
// TODO Provide support for named values
// TODO Provide support for named values
}
}
$this->data = null;
@ -3105,7 +3105,7 @@ class Xls extends BaseReader
$len = min($charsLeft, $limitpos - $pos);
for ($j = 0; $j < $len; ++$j) {
$retstr .= $recordData[$pos + $j]
. chr(0);
. chr(0);
}
$charsLeft -= $len;
$isCompressed = false;
@ -7191,6 +7191,7 @@ class Xls extends BaseReader
{
[$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell);
$baseCol = Coordinate::columnIndexFromString($baseCol) - 1;
$baseRow = (int) $baseRow;
// offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767))
$rowIndex = self::getUInt2d($cellAddressStructure, 0);
@ -7368,8 +7369,8 @@ class Xls extends BaseReader
*/
private function readBIFF8CellRangeAddressB($subData, $baseCell = 'A1')
{
[$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell);
$baseCol = Coordinate::columnIndexFromString($baseCol) - 1;
[$baseCol, $baseRow] = Coordinate::indexesFromString($baseCell);
$baseCol = $baseCol - 1;
// TODO: if cell range is just a single cell, should this funciton
// not just return e.g. 'A1' and not 'A1:A1' ?

View File

@ -5,12 +5,25 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Xls;
class MD5
{
// Context
/**
* @var int
*/
private $a;
/**
* @var int
*/
private $b;
/**
* @var int
*/
private $c;
/**
* @var int
*/
private $d;
/**
@ -56,7 +69,7 @@ class MD5
*
* @param string $data Data to add
*/
public function add($data): void
public function add(string $data): void
{
$words = array_values(unpack('V16', $data));
@ -148,34 +161,34 @@ class MD5
$this->d = ($this->d + $D) & 0xffffffff;
}
private static function f($X, $Y, $Z)
private static function f(int $X, int $Y, int $Z)
{
return ($X & $Y) | ((~$X) & $Z); // X AND Y OR NOT X AND Z
}
private static function g($X, $Y, $Z)
private static function g(int $X, int $Y, int $Z)
{
return ($X & $Z) | ($Y & (~$Z)); // X AND Z OR Y AND NOT Z
}
private static function h($X, $Y, $Z)
private static function h(int $X, int $Y, int $Z)
{
return $X ^ $Y ^ $Z; // X XOR Y XOR Z
}
private static function i($X, $Y, $Z)
private static function i(int $X, int $Y, int $Z)
{
return $Y ^ ($X | (~$Z)); // Y XOR (X OR NOT Z)
}
private static function step($func, &$A, $B, $C, $D, $M, $s, $t): void
private static function step($func, int &$A, int $B, int $C, int $D, int $M, int $s, int $t): void
{
$A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff;
$A = self::rotate($A, $s);
$A = ($B + $A) & 0xffffffff;
}
private static function rotate($decimal, $bits)
private static function rotate(int $decimal, int $bits)
{
$binary = str_pad(decbin($decimal), 32, '0', STR_PAD_LEFT);

View File

@ -272,11 +272,11 @@ class Xlsx extends BaseReader
if (!isset($sharedFormulas[(string) $c->f['si']])) {
$sharedFormulas[$instance] = ['master' => $r, 'formula' => $value];
} else {
$master = Coordinate::coordinateFromString($sharedFormulas[$instance]['master']);
$current = Coordinate::coordinateFromString($r);
$master = Coordinate::indexesFromString($sharedFormulas[$instance]['master']);
$current = Coordinate::indexesFromString($r);
$difference = [0, 0];
$difference[0] = Coordinate::columnIndexFromString($current[0]) - Coordinate::columnIndexFromString($master[0]);
$difference[0] = $current[0] - $master[0];
$difference[1] = $current[1] - $master[1];
$value = $this->referenceHelper->updateFormulaReferences($sharedFormulas[$instance]['formula'], 'A1', $difference[0], $difference[1]);
@ -1141,7 +1141,7 @@ class Xlsx extends BaseReader
)],
false
);
$objDrawing->setCoordinates(Coordinate::stringFromColumnIndex(((string) $oneCellAnchor->from->col) + 1) . ($oneCellAnchor->from->row + 1));
$objDrawing->setCoordinates(Coordinate::stringFromColumnIndex(((int) $oneCellAnchor->from->col) + 1) . ($oneCellAnchor->from->row + 1));
$objDrawing->setOffsetX(Drawing::EMUToPixels($oneCellAnchor->from->colOff));
$objDrawing->setOffsetY(Drawing::EMUToPixels($oneCellAnchor->from->rowOff));
$objDrawing->setResizeProportional(false);
@ -1167,7 +1167,7 @@ class Xlsx extends BaseReader
$objDrawing->setWorksheet($docSheet);
} elseif ($this->includeCharts && $oneCellAnchor->graphicFrame) {
// Exported XLSX from Google Sheets positions charts with a oneCellAnchor
$coordinates = Coordinate::stringFromColumnIndex(((string) $oneCellAnchor->from->col) + 1) . ($oneCellAnchor->from->row + 1);
$coordinates = Coordinate::stringFromColumnIndex(((int) $oneCellAnchor->from->col) + 1) . ($oneCellAnchor->from->row + 1);
$offsetX = Drawing::EMUToPixels($oneCellAnchor->from->colOff);
$offsetY = Drawing::EMUToPixels($oneCellAnchor->from->rowOff);
$width = Drawing::EMUToPixels(self::getArrayItem($oneCellAnchor->ext->attributes(), 'cx'));
@ -1207,7 +1207,7 @@ class Xlsx extends BaseReader
)],
false
);
$objDrawing->setCoordinates(Coordinate::stringFromColumnIndex(((string) $twoCellAnchor->from->col) + 1) . ($twoCellAnchor->from->row + 1));
$objDrawing->setCoordinates(Coordinate::stringFromColumnIndex(((int) $twoCellAnchor->from->col) + 1) . ($twoCellAnchor->from->row + 1));
$objDrawing->setOffsetX(Drawing::EMUToPixels($twoCellAnchor->from->colOff));
$objDrawing->setOffsetY(Drawing::EMUToPixels($twoCellAnchor->from->rowOff));
$objDrawing->setResizeProportional(false);
@ -1233,10 +1233,10 @@ class Xlsx extends BaseReader
$objDrawing->setWorksheet($docSheet);
} elseif (($this->includeCharts) && ($twoCellAnchor->graphicFrame)) {
$fromCoordinate = Coordinate::stringFromColumnIndex(((string) $twoCellAnchor->from->col) + 1) . ($twoCellAnchor->from->row + 1);
$fromCoordinate = Coordinate::stringFromColumnIndex(((int) $twoCellAnchor->from->col) + 1) . ($twoCellAnchor->from->row + 1);
$fromOffsetX = Drawing::EMUToPixels($twoCellAnchor->from->colOff);
$fromOffsetY = Drawing::EMUToPixels($twoCellAnchor->from->rowOff);
$toCoordinate = Coordinate::stringFromColumnIndex(((string) $twoCellAnchor->to->col) + 1) . ($twoCellAnchor->to->row + 1);
$toCoordinate = Coordinate::stringFromColumnIndex(((int) $twoCellAnchor->to->col) + 1) . ($twoCellAnchor->to->row + 1);
$toOffsetX = Drawing::EMUToPixels($twoCellAnchor->to->colOff);
$toOffsetY = Drawing::EMUToPixels($twoCellAnchor->to->rowOff);
$graphic = $twoCellAnchor->graphicFrame->children('http://schemas.openxmlformats.org/drawingml/2006/main')->graphic;
@ -1728,7 +1728,7 @@ class Xlsx extends BaseReader
*
* @return RichText
*/
private function parseRichText($is)
private function parseRichText(?SimpleXMLElement $is)
{
$value = new RichText();
@ -1736,6 +1736,8 @@ class Xlsx extends BaseReader
$value->createText(StringHelper::controlCharacterOOXML2PHP((string) $is->t));
} else {
if (is_object($is->r)) {
/** @var SimpleXMLElement $run */
foreach ($is->r as $run) {
if (!isset($run->rPr)) {
$value->createText(StringHelper::controlCharacterOOXML2PHP((string) $run->t));

View File

@ -90,7 +90,7 @@ class Chart
break;
case 'valAx':
if (isset($chartDetail->title)) {
if (isset($chartDetail->title, $chartDetail->axPos)) {
$axisLabel = self::chartTitle($chartDetail->title->children($namespacesChartMeta['c']), $namespacesChartMeta);
$axPos = self::getAttribute($chartDetail->axPos, 'val', 'string');
@ -355,7 +355,7 @@ class Chart
} elseif (isset($seriesDetail->numRef)) {
$seriesSource = (string) $seriesDetail->numRef->f;
$seriesValues = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, $seriesSource, null, null, null, $marker);
if (isset($seriesDetail->strRef->strCache)) {
if (isset($seriesDetail->numRef->numCache)) {
$seriesData = self::chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c']));
$seriesValues
->setFormatCode($seriesData['formatCode'])
@ -539,7 +539,7 @@ class Chart
{
$plotAttributes = [];
if (isset($chartDetail->dLbls)) {
if (isset($chartDetail->dLbls->howLegendKey)) {
if (isset($chartDetail->dLbls->showLegendKey)) {
$plotAttributes['showLegendKey'] = self::getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string');
}
if (isset($chartDetail->dLbls->showVal)) {

View File

@ -422,6 +422,7 @@ class Xml extends BaseReader
$worksheetID = 0;
$xml_ss = $xml->children($namespaces['ss']);
/** @var null|SimpleXMLElement $worksheetx */
foreach ($xml_ss->Worksheet as $worksheetx) {
$worksheet = $worksheetx ?? new SimpleXMLElement('<xml></xml>');
$worksheet_ss = self::getAttributes($worksheet, $namespaces['ss']);
@ -748,9 +749,6 @@ class Xml extends BaseReader
private static $borderPositions = ['top', 'left', 'bottom', 'right'];
/**
* @param $styleID
*/
private function parseStyleBorders($styleID, SimpleXMLElement $styleData, array $namespaces): void
{
$diagonalDirection = '';
@ -821,9 +819,6 @@ class Xml extends BaseReader
}
}
/**
* @param $styleID
*/
private function parseStyleFont(string $styleID, SimpleXMLElement $styleAttributes): void
{
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValue) {
@ -861,9 +856,6 @@ class Xml extends BaseReader
}
}
/**
* @param $styleID
*/
private function parseStyleInterior($styleID, SimpleXMLElement $styleAttributes): void
{
foreach ($styleAttributes as $styleAttributeKey => $styleAttributeValuex) {
@ -887,9 +879,6 @@ class Xml extends BaseReader
}
}
/**
* @param $styleID
*/
private function parseStyleNumberFormat($styleID, SimpleXMLElement $styleAttributes): void
{
$fromFormats = ['\-', '\ '];

View File

@ -375,17 +375,16 @@ class ReferenceHelper
$allCoordinates = $pSheet->getCoordinates();
// Get coordinate of $pBefore
[$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($pBefore);
$beforeColumnIndex = Coordinate::columnIndexFromString($beforeColumn);
[$beforeColumn, $beforeRow] = Coordinate::indexesFromString($pBefore);
// Clear cells if we are removing columns or rows
$highestColumn = $pSheet->getHighestColumn();
$highestRow = $pSheet->getHighestRow();
// 1. Clear column strips if we are removing columns
if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) {
if ($pNumCols < 0 && $beforeColumn - 2 + $pNumCols > 0) {
for ($i = 1; $i <= $highestRow - 1; ++$i) {
for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) {
for ($j = $beforeColumn - 1 + $pNumCols; $j <= $beforeColumn - 2; ++$j) {
$coordinate = Coordinate::stringFromColumnIndex($j + 1) . $i;
$pSheet->removeConditionalStyles($coordinate);
if ($pSheet->cellExists($coordinate)) {
@ -398,7 +397,7 @@ class ReferenceHelper
// 2. Clear row strips if we are removing rows
if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) {
for ($i = $beforeColumnIndex - 1; $i <= Coordinate::columnIndexFromString($highestColumn) - 1; ++$i) {
for ($i = $beforeColumn - 1; $i <= Coordinate::columnIndexFromString($highestColumn) - 1; ++$i) {
for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) {
$coordinate = Coordinate::stringFromColumnIndex($i + 1) . $j;
$pSheet->removeConditionalStyles($coordinate);
@ -427,7 +426,7 @@ class ReferenceHelper
$newCoordinate = Coordinate::stringFromColumnIndex($cellIndex + $pNumCols) . ($cell->getRow() + $pNumRows);
// Should the cell be updated? Move value and cellXf index from one cell to another.
if (($cellIndex >= $beforeColumnIndex) && ($cell->getRow() >= $beforeRow)) {
if (($cellIndex >= $beforeColumn) && ($cell->getRow() >= $beforeRow)) {
// Update cell styles
$pSheet->getCell($newCoordinate)->setXfIndex($cell->getXfIndex());
@ -457,15 +456,15 @@ class ReferenceHelper
$highestColumn = $pSheet->getHighestColumn();
$highestRow = $pSheet->getHighestRow();
if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) {
if ($pNumCols > 0 && $beforeColumn - 2 > 0) {
for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) {
// Style
$coordinate = Coordinate::stringFromColumnIndex($beforeColumnIndex - 1) . $i;
$coordinate = Coordinate::stringFromColumnIndex($beforeColumn - 1) . $i;
if ($pSheet->cellExists($coordinate)) {
$xfIndex = $pSheet->getCell($coordinate)->getXfIndex();
$conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ?
$pSheet->getConditionalStyles($coordinate) : false;
for ($j = $beforeColumnIndex; $j <= $beforeColumnIndex - 1 + $pNumCols; ++$j) {
for ($j = $beforeColumn; $j <= $beforeColumn - 1 + $pNumCols; ++$j) {
$pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex);
if ($conditionalStyles) {
$cloned = [];
@ -480,7 +479,7 @@ class ReferenceHelper
}
if ($pNumRows > 0 && $beforeRow - 1 > 0) {
for ($i = $beforeColumnIndex; $i <= Coordinate::columnIndexFromString($highestColumn); ++$i) {
for ($i = $beforeColumn; $i <= Coordinate::columnIndexFromString($highestColumn); ++$i) {
// Style
$coordinate = Coordinate::stringFromColumnIndex($i) . ($beforeRow - 1);
if ($pSheet->cellExists($coordinate)) {
@ -502,28 +501,28 @@ class ReferenceHelper
}
// Update worksheet: column dimensions
$this->adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustColumnDimensions($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: row dimensions
$this->adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustRowDimensions($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: page breaks
$this->adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustPageBreaks($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: comments
$this->adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustComments($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: hyperlinks
$this->adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustHyperlinks($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: data validations
$this->adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustDataValidations($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: merge cells
$this->adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustMergeCells($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: protected cells
$this->adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows);
$this->adjustProtectedCells($pSheet, $pBefore, $beforeColumn, $pNumCols, $beforeRow, $pNumRows);
// Update worksheet: autofilter
$autoFilter = $pSheet->getAutoFilter();
@ -654,7 +653,7 @@ class ReferenceHelper
$toString .= $modified3 . ':' . $modified4;
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
$column = 100000;
$row = 10000000 + trim($match[3], '$');
$row = 10000000 + (int) trim($match[3], '$');
$cellIndex = $column . $row;
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
@ -705,7 +704,7 @@ class ReferenceHelper
[$column, $row] = Coordinate::coordinateFromString($match[3]);
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
$column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000;
$row = trim($row, '$') + 10000000;
$row = (int) trim($row, '$') + 10000000;
$cellIndex = $column . $row;
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
@ -731,7 +730,7 @@ class ReferenceHelper
[$column, $row] = Coordinate::coordinateFromString($match[3]);
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
$column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000;
$row = trim($row, '$') + 10000000;
$row = (int) trim($row, '$') + 10000000;
$cellIndex = $row . $column;
$newCellTokens[$cellIndex] = preg_quote($toString, '/');
@ -1021,7 +1020,7 @@ class ReferenceHelper
// Create new row reference
if ($updateRow) {
$newRow = $newRow + $pNumRows;
$newRow = (int) $newRow + $pNumRows;
}
// Return new reference

View File

@ -14,7 +14,7 @@ interface ITextElement
/**
* Set text.
*
* @param $text string Text
* @param string $text Text
*
* @return ITextElement
*/

View File

@ -35,7 +35,7 @@ class TextElement implements ITextElement
/**
* Set text.
*
* @param $text string Text
* @param string $text Text
*
* @return $this
*/

View File

@ -304,8 +304,8 @@ class Date
}
// Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0)
$century = substr($year, 0, 2);
$decade = substr($year, 2, 2);
$century = (int) substr($year, 0, 2);
$decade = (int) substr($year, 2, 2);
$excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $myexcelBaseDate + $excel1900isLeapYear;
$excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400;

View File

@ -273,14 +273,8 @@ class Font
/**
* Get GD text width in pixels for a string of text in a certain font at a certain rotation angle.
*
* @param string $text
* @param \PhpOffice\PhpSpreadsheet\Style\Font
* @param int $rotation
*
* @return int
*/
public static function getTextWidthPixelsExact($text, \PhpOffice\PhpSpreadsheet\Style\Font $font, $rotation = 0)
public static function getTextWidthPixelsExact(string $text, \PhpOffice\PhpSpreadsheet\Style\Font $font, int $rotation = 0): int
{
if (!function_exists('imagettfbbox')) {
throw new PhpSpreadsheetException('GD library needs to be enabled');
@ -350,7 +344,7 @@ class Font
} else {
// rotated text
$columnWidth = $columnWidth * cos(deg2rad($rotation))
+ $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation
+ $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation
}
}
@ -415,35 +409,35 @@ class Font
switch ($name) {
case 'Arial':
$fontFile = (
$bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD)
: ($italic ? self::ARIAL_ITALIC : self::ARIAL)
$bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD)
: ($italic ? self::ARIAL_ITALIC : self::ARIAL)
);
break;
case 'Calibri':
$fontFile = (
$bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD)
: ($italic ? self::CALIBRI_ITALIC : self::CALIBRI)
$bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD)
: ($italic ? self::CALIBRI_ITALIC : self::CALIBRI)
);
break;
case 'Courier New':
$fontFile = (
$bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD)
: ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW)
$bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD)
: ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW)
);
break;
case 'Comic Sans MS':
$fontFile = (
$bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS
$bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS
);
break;
case 'Georgia':
$fontFile = (
$bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD)
: ($italic ? self::GEORGIA_ITALIC : self::GEORGIA)
$bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD)
: ($italic ? self::GEORGIA_ITALIC : self::GEORGIA)
);
break;
@ -453,8 +447,8 @@ class Font
break;
case 'Liberation Sans':
$fontFile = (
$bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD)
: ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS)
$bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD)
: ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS)
);
break;
@ -472,8 +466,8 @@ class Font
break;
case 'Palatino Linotype':
$fontFile = (
$bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD)
: ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE)
$bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD)
: ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE)
);
break;
@ -483,28 +477,28 @@ class Font
break;
case 'Tahoma':
$fontFile = (
$bold ? self::TAHOMA_BOLD : self::TAHOMA
$bold ? self::TAHOMA_BOLD : self::TAHOMA
);
break;
case 'Times New Roman':
$fontFile = (
$bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD)
: ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN)
$bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD)
: ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN)
);
break;
case 'Trebuchet MS':
$fontFile = (
$bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD)
: ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS)
$bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD)
: ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS)
);
break;
case 'Verdana':
$fontFile = (
$bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD)
: ($italic ? self::VERDANA_ITALIC : self::VERDANA)
$bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD)
: ($italic ? self::VERDANA_ITALIC : self::VERDANA)
);
break;
@ -563,13 +557,13 @@ class Font
// Exact width can be determined
$columnWidth = $pPixels ?
self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px']
: self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width'];
: self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width'];
} else {
// We don't have data for this particular font and size, use approximation by
// extrapolating from Calibri 11
$columnWidth = $pPixels ?
self::$defaultColumnWidths['Calibri'][11]['px']
: self::$defaultColumnWidths['Calibri'][11]['width'];
: self::$defaultColumnWidths['Calibri'][11]['width'];
$columnWidth = $columnWidth * $font->getSize() / 11;
// Round pixels to closest integer

View File

@ -103,7 +103,7 @@ class CholeskyDecomposition
/**
* Solve A*X = B.
*
* @param $B Row-equal matrix
* @param Matrix $B Row-equal matrix
*
* @return Matrix L * L' * X = B
*/
@ -111,7 +111,7 @@ class CholeskyDecomposition
{
if ($B->getRowDimension() == $this->m) {
if ($this->isspd) {
$X = $B->getArrayCopy();
$X = $B->getArray();
$nx = $B->getColumnDimension();
for ($k = 0; $k < $this->m; ++$k) {

View File

@ -456,17 +456,6 @@ class Matrix
return $s;
}
/**
* uminus.
*
* Unary minus matrix -A
*
* @return Matrix Unary minus matrix
*/
public function uminus()
{
}
/**
* plus.
*

View File

@ -15,9 +15,9 @@ use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalculationException;
* of simultaneous linear equations. This will fail if isFullRank()
* returns false.
*
* @author Paul Meagher
* @author Paul Meagher
*
* @version 1.1
* @version 1.1
*/
class QRDecomposition
{
@ -54,47 +54,43 @@ class QRDecomposition
/**
* QR Decomposition computed by Householder reflections.
*
* @param matrix $A Rectangular matrix
* @param Matrix $A Rectangular matrix
*/
public function __construct($A)
public function __construct(Matrix $A)
{
if ($A instanceof Matrix) {
// Initialize.
$this->QR = $A->getArray();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
// Main loop.
for ($k = 0; $k < $this->n; ++$k) {
// Compute 2-norm of k-th column without under/overflow.
$nrm = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$nrm = hypo($nrm, $this->QR[$i][$k]);
}
if ($nrm != 0.0) {
// Form k-th Householder vector.
if ($this->QR[$k][$k] < 0) {
$nrm = -$nrm;
}
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$k] /= $nrm;
}
$this->QR[$k][$k] += 1.0;
// Apply transformation to remaining columns.
for ($j = $k + 1; $j < $this->n; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $this->QR[$i][$j];
}
$s = -$s / $this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
$this->Rdiag[$k] = -$nrm;
// Initialize.
$this->QR = $A->getArray();
$this->m = $A->getRowDimension();
$this->n = $A->getColumnDimension();
// Main loop.
for ($k = 0; $k < $this->n; ++$k) {
// Compute 2-norm of k-th column without under/overflow.
$nrm = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$nrm = hypo($nrm, $this->QR[$i][$k]);
}
} else {
throw new CalculationException(Matrix::ARGUMENT_TYPE_EXCEPTION);
if ($nrm != 0.0) {
// Form k-th Householder vector.
if ($this->QR[$k][$k] < 0) {
$nrm = -$nrm;
}
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$k] /= $nrm;
}
$this->QR[$k][$k] += 1.0;
// Apply transformation to remaining columns.
for ($j = $k + 1; $j < $this->n; ++$j) {
$s = 0.0;
for ($i = $k; $i < $this->m; ++$i) {
$s += $this->QR[$i][$k] * $this->QR[$i][$j];
}
$s = -$s / $this->QR[$k][$k];
for ($i = $k; $i < $this->m; ++$i) {
$this->QR[$i][$j] += $s * $this->QR[$i][$k];
}
}
}
$this->Rdiag[$k] = -$nrm;
}
}
@ -211,7 +207,7 @@ class QRDecomposition
if ($this->isFullRank()) {
// Copy right hand side
$nx = $B->getColumnDimension();
$X = $B->getArrayCopy();
$X = $B->getArray();
// Compute Y = transpose(Q)*B
for ($k = 0; $k < $this->n; ++$k) {
for ($j = 0; $j < $nx; ++$j) {

View File

@ -65,7 +65,7 @@ class SingularValueDecomposition
public function __construct($Arg)
{
// Initialize.
$A = $Arg->getArrayCopy();
$A = $Arg->getArray();
$this->m = $Arg->getRowDimension();
$this->n = $Arg->getColumnDimension();
$nu = min($this->m, $this->n);

View File

@ -42,7 +42,7 @@ class ChainedBlockStream
* ole-chainedblockstream://oleInstanceId=1
* @param string $mode only "r" is supported
* @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH
* @param string &$openedPath absolute path of the opened stream (out parameter)
* @param string $openedPath absolute path of the opened stream (out parameter)
*
* @return bool true on success
*/

View File

@ -200,7 +200,7 @@ class PPS
* Updates index and pointers to previous, next and children PPS's for this
* PPS. I don't think it'll work with Dir PPS's.
*
* @param array &$raList Reference to the array of PPS's for the whole OLE
* @param array $raList Reference to the array of PPS's for the whole OLE
* container
* @param mixed $to_save
* @param mixed $depth

View File

@ -237,7 +237,7 @@ class Root extends PPS
* Saving big data (PPS's with data bigger than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
*
* @param int $iStBlk
* @param array &$raList Reference to array of PPS's
* @param array $raList Reference to array of PPS's
*/
private function saveBigData($iStBlk, &$raList): void
{
@ -267,7 +267,7 @@ class Root extends PPS
/**
* get small data (PPS's with data smaller than \PhpOffice\PhpSpreadsheet\Shared\OLE::OLE_DATA_SIZE_SMALL).
*
* @param array &$raList Reference to array of PPS's
* @param array $raList Reference to array of PPS's
*
* @return string
*/

View File

@ -92,10 +92,8 @@ class OLERead
/**
* Read the file.
*
* @param $pFilename string Filename
*/
public function read($pFilename): void
public function read(string $pFilename): void
{
File::assertFile($pFilename);

View File

@ -556,7 +556,7 @@ class StringHelper
* Identify whether a string contains a fractional numeric value,
* and convert it to a numeric if it is.
*
* @param string &$operand string value to test
* @param string $operand string value to test
*
* @return bool
*/

View File

@ -44,7 +44,7 @@ class Trend
/**
* Cached results for each method when trying to identify which provides the best fit.
*
* @var bestFit[]
* @var BestFit[]
*/
private static $trendCache = [];

View File

@ -209,8 +209,7 @@ class Xls
*/
public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height)
{
[$column, $row] = Coordinate::coordinateFromString($coordinates);
$col_start = Coordinate::columnIndexFromString($column);
[$col_start, $row] = Coordinate::indexesFromString($coordinates);
$row_start = $row - 1;
$x1 = $offsetX;

View File

@ -70,17 +70,19 @@ class Border extends Supervisor
*/
public function getSharedComponent()
{
/** @var Borders $sharedComponent */
$sharedComponent = $this->parent->getSharedComponent();
switch ($this->parentPropertyName) {
case 'bottom':
return $this->parent->getSharedComponent()->getBottom();
return $sharedComponent->getBottom();
case 'diagonal':
return $this->parent->getSharedComponent()->getDiagonal();
return $sharedComponent->getDiagonal();
case 'left':
return $this->parent->getSharedComponent()->getLeft();
return $sharedComponent->getLeft();
case 'right':
return $this->parent->getSharedComponent()->getRight();
return $sharedComponent->getRight();
case 'top':
return $this->parent->getSharedComponent()->getTop();
return $sharedComponent->getTop();
}
throw new PhpSpreadsheetException('Cannot get shared component for a pseudo-border.');

View File

@ -71,14 +71,16 @@ class Color extends Supervisor
*/
public function getSharedComponent()
{
/** @var Border|Fill $sharedComponent */
$sharedComponent = $this->parent->getSharedComponent();
if ($this->parentPropertyName === 'endColor') {
return $this->parent->getSharedComponent()->getEndColor();
return $sharedComponent->getEndColor();
}
if ($this->parentPropertyName === 'startColor') {
return $this->parent->getSharedComponent()->getStartColor();
return $sharedComponent->getStartColor();
}
return $this->parent->getSharedComponent()->getColor();
return $sharedComponent->getColor();
}
/**
@ -200,7 +202,7 @@ class Color extends Supervisor
* @param bool $hex Flag indicating whether the component should be returned as a hex or a
* decimal value
*
* @return string The extracted colour component
* @return int|string The extracted colour component
*/
private static function getColourComponent($RGB, $offset, $hex = true)
{
@ -216,7 +218,7 @@ class Color extends Supervisor
* @param bool $hex Flag indicating whether the component should be returned as a hex or a
* decimal value
*
* @return string The red colour component
* @return int|string The red colour component
*/
public static function getRed($RGB, $hex = true)
{
@ -230,7 +232,7 @@ class Color extends Supervisor
* @param bool $hex Flag indicating whether the component should be returned as a hex or a
* decimal value
*
* @return string The green colour component
* @return int|string The green colour component
*/
public static function getGreen($RGB, $hex = true)
{
@ -244,7 +246,7 @@ class Color extends Supervisor
* @param bool $hex Flag indicating whether the component should be returned as a hex or a
* decimal value
*
* @return string The blue colour component
* @return int|string The blue colour component
*/
public static function getBlue($RGB, $hex = true)
{
@ -264,8 +266,11 @@ class Color extends Supervisor
$rgba = (strlen($hex) === 8);
$adjustPercentage = max(-1.0, min(1.0, $adjustPercentage));
/** @var int $red */
$red = self::getRed($hex, false);
/** @var int $green */
$green = self::getGreen($hex, false);
/** @var int $blue */
$blue = self::getBlue($hex, false);
if ($adjustPercentage > 0) {
$red += (255 - $red) * $adjustPercentage;

View File

@ -13,8 +13,6 @@ class ConditionalFormatValueObject
/**
* ConditionalFormatValueObject constructor.
*
* @param $type
* @param $value
* @param null|mixed $cellFormula
*/
public function __construct($type, $value = null, $cellFormula = null)

View File

@ -24,8 +24,6 @@ class ConditionalFormattingRuleExtension
/**
* ConditionalFormattingRuleExtension constructor.
*
* @param $id
*/
public function __construct($id = null, string $cfRule = self::CONDITION_EXTENSION_DATABAR)
{

View File

@ -202,18 +202,17 @@ class Style extends Supervisor
// Calculate range outer borders
$rangeStart = Coordinate::coordinateFromString($rangeA);
$rangeEnd = Coordinate::coordinateFromString($rangeB);
$rangeStartIndexes = Coordinate::indexesFromString($rangeA);
$rangeEndIndexes = Coordinate::indexesFromString($rangeB);
// Translate column into index
$rangeStart0 = $rangeStart[0];
$rangeEnd0 = $rangeEnd[0];
$rangeStart[0] = Coordinate::columnIndexFromString($rangeStart[0]);
$rangeEnd[0] = Coordinate::columnIndexFromString($rangeEnd[0]);
$columnStart = $rangeStart[0];
$columnEnd = $rangeEnd[0];
// Make sure we can loop upwards on rows and columns
if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
$tmp = $rangeStart;
$rangeStart = $rangeEnd;
$rangeEnd = $tmp;
if ($rangeStartIndexes[0] > $rangeEndIndexes[0] && $rangeStartIndexes[1] > $rangeEndIndexes[1]) {
$tmp = $rangeStartIndexes;
$rangeStartIndexes = $rangeEndIndexes;
$rangeEndIndexes = $tmp;
}
// ADVANCED MODE:
@ -249,19 +248,19 @@ class Style extends Supervisor
unset($pStyles['borders']['inside']); // not needed any more
}
// width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
$xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3);
$yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3);
$xMax = min($rangeEndIndexes[0] - $rangeStartIndexes[0] + 1, 3);
$yMax = min($rangeEndIndexes[1] - $rangeStartIndexes[1] + 1, 3);
// loop through up to 3 x 3 = 9 regions
for ($x = 1; $x <= $xMax; ++$x) {
// start column index for region
$colStart = ($x == 3) ?
Coordinate::stringFromColumnIndex($rangeEnd[0])
: Coordinate::stringFromColumnIndex($rangeStart[0] + $x - 1);
Coordinate::stringFromColumnIndex($rangeEndIndexes[0])
: Coordinate::stringFromColumnIndex($rangeStartIndexes[0] + $x - 1);
// end column index for region
$colEnd = ($x == 1) ?
Coordinate::stringFromColumnIndex($rangeStart[0])
: Coordinate::stringFromColumnIndex($rangeEnd[0] - $xMax + $x);
Coordinate::stringFromColumnIndex($rangeStartIndexes[0])
: Coordinate::stringFromColumnIndex($rangeEndIndexes[0] - $xMax + $x);
for ($y = 1; $y <= $yMax; ++$y) {
// which edges are touching the region
@ -285,11 +284,11 @@ class Style extends Supervisor
// start row index for region
$rowStart = ($y == 3) ?
$rangeEnd[1] : $rangeStart[1] + $y - 1;
$rangeEndIndexes[1] : $rangeStartIndexes[1] + $y - 1;
// end row index for region
$rowEnd = ($y == 1) ?
$rangeStart[1] : $rangeEnd[1] - $yMax + $y;
$rangeStartIndexes[1] : $rangeEndIndexes[1] - $yMax + $y;
// build range for region
$range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
@ -349,7 +348,7 @@ class Style extends Supervisor
}
// First loop through columns, rows, or cells to find out which styles are affected by this operation
$oldXfIndexes = $this->getOldXfIndexes($selectionType, $rangeStart, $rangeEnd, $rangeStart0, $rangeEnd0, $pStyles);
$oldXfIndexes = $this->getOldXfIndexes($selectionType, $rangeStartIndexes, $rangeEndIndexes, $columnStart, $columnEnd, $pStyles);
// clone each of the affected styles, apply the style array, and add the new styles to the workbook
$workbook = $this->getActiveSheet()->getParent();
@ -372,7 +371,7 @@ class Style extends Supervisor
// Loop through columns, rows, or cells again and update the XF index
switch ($selectionType) {
case 'COLUMN':
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
for ($col = $rangeStartIndexes[0]; $col <= $rangeEndIndexes[0]; ++$col) {
$columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col);
$oldXfIndex = $columnDimension->getXfIndex();
$columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
@ -380,7 +379,7 @@ class Style extends Supervisor
break;
case 'ROW':
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
for ($row = $rangeStartIndexes[1]; $row <= $rangeEndIndexes[1]; ++$row) {
$rowDimension = $this->getActiveSheet()->getRowDimension($row);
// row without explicit style should be formatted based on default style
$oldXfIndex = $rowDimension->getXfIndex() ?? 0;
@ -389,8 +388,8 @@ class Style extends Supervisor
break;
case 'CELL':
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
for ($col = $rangeStartIndexes[0]; $col <= $rangeEndIndexes[0]; ++$col) {
for ($row = $rangeStartIndexes[1]; $row <= $rangeEndIndexes[1]; ++$row) {
$cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row);
$oldXfIndex = $cell->getXfIndex();
$cell->setXfIndex($newXfIndexes[$oldXfIndex]);
@ -427,7 +426,7 @@ class Style extends Supervisor
return $this;
}
private function getOldXfIndexes(string $selectionType, array $rangeStart, array $rangeEnd, string $rangeStart0, string $rangeEnd0, array $pStyles): array
private function getOldXfIndexes(string $selectionType, array $rangeStart, array $rangeEnd, string $columnStart, string $columnEnd, array $pStyles): array
{
$oldXfIndexes = [];
switch ($selectionType) {
@ -435,7 +434,7 @@ class Style extends Supervisor
for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
$oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
}
foreach ($this->getActiveSheet()->getColumnIterator($rangeStart0, $rangeEnd0) as $columnIterator) {
foreach ($this->getActiveSheet()->getColumnIterator($columnStart, $columnEnd) as $columnIterator) {
$cellIterator = $columnIterator->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true);
foreach ($cellIterator as $columnCell) {

View File

@ -780,7 +780,7 @@ class AutoFilter
$ruleValues = [];
$dataRowCount = $rangeEnd[1] - $rangeStart[1];
$toptenRuleType = null;
$ruleValue = null;
$ruleValue = 0;
$ruleOperator = null;
foreach ($rules as $rule) {
// We should only ever have one Dynamic Filter Rule anyway

View File

@ -96,14 +96,14 @@ class Worksheet implements IComparable
/**
* Collection of drawings.
*
* @var BaseDrawing[]
* @var ArrayObject<BaseDrawing>
*/
private $drawingCollection;
/**
* Collection of Chart objects.
*
* @var Chart[]
* @var ArrayObject<Chart>
*/
private $chartCollection = [];
@ -180,7 +180,7 @@ class Worksheet implements IComparable
/**
* Collection of breaks.
*
* @var array
* @var int[]
*/
private $breaks = [];
@ -534,7 +534,7 @@ class Worksheet implements IComparable
/**
* Get collection of drawings.
*
* @return BaseDrawing[]
* @return ArrayObject<BaseDrawing>
*/
public function getDrawingCollection()
{
@ -544,7 +544,7 @@ class Worksheet implements IComparable
/**
* Get collection of charts.
*
* @return Chart[]
* @return ArrayObject<Chart>
*/
public function getChartCollection()
{
@ -1482,7 +1482,7 @@ class Worksheet implements IComparable
* Set conditional styles.
*
* @param string $pCoordinate eg: 'A1'
* @param $pValue Conditional[]
* @param Conditional[] $pValue
*
* @return $this
*/
@ -1640,7 +1640,7 @@ class Worksheet implements IComparable
/**
* Get breaks.
*
* @return array[]
* @return int[]
*/
public function getBreaks()
{

View File

@ -453,10 +453,8 @@ class Html extends BaseWriter
// Get worksheet dimension
[$min, $max] = explode(':', $sheet->calculateWorksheetDataDimension());
[$minCol, $minRow] = Coordinate::coordinateFromString($min);
$minCol = Coordinate::columnIndexFromString($minCol);
[$maxCol, $maxRow] = Coordinate::coordinateFromString($max);
$maxCol = Coordinate::columnIndexFromString($maxCol);
[$minCol, $minRow] = Coordinate::indexesFromString($min);
[$maxCol, $maxRow] = Coordinate::indexesFromString($max);
[$theadStart, $theadEnd, $tbodyStart] = $this->generateSheetStarts($sheet, $minRow);
@ -1703,11 +1701,11 @@ class Html extends BaseWriter
$first = $cells[0];
$last = $cells[1];
[$fc, $fr] = Coordinate::coordinateFromString($first);
$fc = Coordinate::columnIndexFromString($fc) - 1;
[$fc, $fr] = Coordinate::indexesFromString($first);
$fc = $fc - 1;
[$lc, $lr] = Coordinate::coordinateFromString($last);
$lc = Coordinate::columnIndexFromString($lc) - 1;
[$lc, $lr] = Coordinate::indexesFromString($last);
$lc = $lc - 1;
// loop through the individual cells in the individual merge
$r = $fr - 1;

View File

@ -2,7 +2,6 @@
namespace PhpOffice\PhpSpreadsheet\Writer;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
use PhpOffice\PhpSpreadsheet\Writer\Ods\Content;
@ -32,6 +31,41 @@ class Ods extends BaseWriter
*/
private $spreadSheet;
/**
* @var Content
*/
private $writerPartContent;
/**
* @var Meta
*/
private $writerPartMeta;
/**
* @var MetaInf
*/
private $writerPartMetaInf;
/**
* @var Mimetype
*/
private $writerPartMimetype;
/**
* @var Settings
*/
private $writerPartSettings;
/**
* @var Styles
*/
private $writerPartStyles;
/**
* @var Thumbnails
*/
private $writerPartThumbnails;
/**
* Create a new Ods.
*/
@ -39,35 +73,48 @@ class Ods extends BaseWriter
{
$this->setSpreadsheet($spreadsheet);
$writerPartsArray = [
'content' => Content::class,
'meta' => Meta::class,
'meta_inf' => MetaInf::class,
'mimetype' => Mimetype::class,
'settings' => Settings::class,
'styles' => Styles::class,
'thumbnails' => Thumbnails::class,
];
foreach ($writerPartsArray as $writer => $class) {
$this->writerParts[$writer] = new $class($this);
}
$this->writerPartContent = new Content($this);
$this->writerPartMeta = new Meta($this);
$this->writerPartMetaInf = new MetaInf($this);
$this->writerPartMimetype = new Mimetype($this);
$this->writerPartSettings = new Settings($this);
$this->writerPartStyles = new Styles($this);
$this->writerPartThumbnails = new Thumbnails($this);
}
/**
* Get writer part.
*
* @param string $pPartName Writer part name
*
* @return null|Ods\WriterPart
*/
public function getWriterPart($pPartName)
public function getWriterPartContent(): Content
{
if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
return $this->writerParts[strtolower($pPartName)];
}
return $this->writerPartContent;
}
return null;
public function getWriterPartMeta(): Meta
{
return $this->writerPartMeta;
}
public function getWriterPartMetaInf(): MetaInf
{
return $this->writerPartMetaInf;
}
public function getWriterPartMimetype(): Mimetype
{
return $this->writerPartMimetype;
}
public function getWriterPartSettings(): Settings
{
return $this->writerPartSettings;
}
public function getWriterPartStyles(): Styles
{
return $this->writerPartStyles;
}
public function getWriterPartThumbnails(): Thumbnails
{
return $this->writerPartThumbnails;
}
/**
@ -88,13 +135,13 @@ class Ods extends BaseWriter
$zip = $this->createZip();
$zip->addFile('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
$zip->addFile('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
$zip->addFile('content.xml', $this->getWriterPart('content')->write());
$zip->addFile('meta.xml', $this->getWriterPart('meta')->write());
$zip->addFile('mimetype', $this->getWriterPart('mimetype')->write());
$zip->addFile('settings.xml', $this->getWriterPart('settings')->write());
$zip->addFile('styles.xml', $this->getWriterPart('styles')->write());
$zip->addFile('META-INF/manifest.xml', $this->getWriterPartMetaInf()->write());
$zip->addFile('Thumbnails/thumbnail.png', $this->getWriterPartthumbnails()->write());
$zip->addFile('content.xml', $this->getWriterPartcontent()->write());
$zip->addFile('meta.xml', $this->getWriterPartmeta()->write());
$zip->addFile('mimetype', $this->getWriterPartmimetype()->write());
$zip->addFile('settings.xml', $this->getWriterPartsettings()->write());
$zip->addFile('styles.xml', $this->getWriterPartstyles()->write());
// Close file
try {

View File

@ -39,7 +39,7 @@ class Content extends WriterPart
*
* @return string XML Output
*/
public function write()
public function write(): string
{
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {

View File

@ -3,22 +3,17 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Meta extends WriterPart
{
/**
* Write meta.xml to XML format.
*
* @param Spreadsheet $spreadsheet
*
* @return string XML Output
*/
public function write(?Spreadsheet $spreadsheet = null)
public function write(): string
{
if (!$spreadsheet) {
$spreadsheet = $this->getParentWriter()->getSpreadsheet();
}
$spreadsheet = $this->getParentWriter()->getSpreadsheet();
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {

View File

@ -11,7 +11,7 @@ class MetaInf extends WriterPart
*
* @return string XML Output
*/
public function writeManifest()
public function write(): string
{
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {

View File

@ -2,18 +2,14 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Mimetype extends WriterPart
{
/**
* Write mimetype to plain text format.
*
* @param Spreadsheet $spreadsheet
*
* @return string XML Output
*/
public function write(?Spreadsheet $spreadsheet = null)
public function write(): string
{
return 'application/vnd.oasis.opendocument.spreadsheet';
}

View File

@ -23,11 +23,13 @@ class NamedExpressions
$this->formulaConvertor = $formulaConvertor;
}
public function write(): void
public function write(): string
{
$this->objWriter->startElement('table:named-expressions');
$this->writeExpressions();
$this->objWriter->endElement();
return '';
}
private function writeExpressions(): void

View File

@ -4,18 +4,15 @@ namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Settings extends WriterPart
{
/**
* Write settings.xml to XML format.
*
* @param Spreadsheet $spreadsheet
*
* @return string XML Output
*/
public function write(?Spreadsheet $spreadsheet = null)
public function write(): string
{
if ($this->getParentWriter()->getUseDiskCaching()) {
$objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
@ -40,7 +37,7 @@ class Settings extends WriterPart
$objWriter->startElement('config:config-item-map-indexed');
$objWriter->writeAttribute('config:name', 'Views');
$objWriter->startElement('config:config-item-map-entry');
$spreadsheet = $spreadsheet ?? $this->getParentWriter()->getSpreadsheet();
$spreadsheet = $this->getParentWriter()->getSpreadsheet();
$objWriter->startElement('config:config-item');
$objWriter->writeAttribute('config:name', 'ViewId');

View File

@ -3,18 +3,15 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Styles extends WriterPart
{
/**
* Write styles.xml to XML format.
*
* @param Spreadsheet $spreadsheet
*
* @return string XML Output
*/
public function write(?Spreadsheet $spreadsheet = null)
public function write(): string
{
$objWriter = null;
if ($this->getParentWriter()->getUseDiskCaching()) {

View File

@ -2,18 +2,14 @@
namespace PhpOffice\PhpSpreadsheet\Writer\Ods;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
class Thumbnails extends WriterPart
{
/**
* Write Thumbnails/thumbnail.png to PNG format.
*
* @param Spreadsheet $spreadsheet
*
* @return string XML Output
*/
public function writeThumbnail(?Spreadsheet $spreadsheet = null)
public function write(): string
{
return '';
}

View File

@ -30,4 +30,6 @@ abstract class WriterPart
{
$this->parentWriter = $writer;
}
abstract public function write(): string;
}

View File

@ -23,6 +23,9 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
use PhpOffice\PhpSpreadsheet\Writer\Xls\Parser;
use PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook;
use PhpOffice\PhpSpreadsheet\Writer\Xls\Worksheet;
class Xls extends BaseWriter
{
@ -64,7 +67,7 @@ class Xls extends BaseWriter
/**
* Formula parser.
*
* @var \PhpOffice\PhpSpreadsheet\Writer\Xls\Parser
* @var Parser
*/
private $parser;
@ -90,12 +93,12 @@ class Xls extends BaseWriter
private $documentSummaryInformation;
/**
* @var \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook
* @var Workbook
*/
private $writerWorkbook;
/**
* @var \PhpOffice\PhpSpreadsheet\Writer\Xls\Worksheet[]
* @var Worksheet[]
*/
private $writerWorksheets;
@ -388,7 +391,7 @@ class Xls extends BaseWriter
}
}
private function processMemoryDrawing(BstoreContainer &$bstoreContainer, BaseDrawing $drawing, string $renderingFunctionx): void
private function processMemoryDrawing(BstoreContainer &$bstoreContainer, MemoryDrawing $drawing, string $renderingFunctionx): void
{
switch ($renderingFunctionx) {
case MemoryDrawing::RENDERING_JPEG:
@ -418,7 +421,7 @@ class Xls extends BaseWriter
$bstoreContainer->addBSE($BSE);
}
private function processDrawing(BstoreContainer &$bstoreContainer, BaseDrawing $drawing): void
private function processDrawing(BstoreContainer &$bstoreContainer, Drawing $drawing): void
{
$blipType = null;
$blipData = '';

View File

@ -420,8 +420,8 @@ class Escher
$recType = 0xF010;
// start coordinates
[$column, $row] = Coordinate::coordinateFromString($this->object->getStartCoordinates());
$c1 = Coordinate::columnIndexFromString($column) - 1;
[$column, $row] = Coordinate::indexesFromString($this->object->getStartCoordinates());
$c1 = $column - 1;
$r1 = $row - 1;
// start offsetX
@ -431,8 +431,8 @@ class Escher
$startOffsetY = $this->object->getStartOffsetY();
// end coordinates
[$column, $row] = Coordinate::coordinateFromString($this->object->getEndCoordinates());
$c2 = Coordinate::columnIndexFromString($column) - 1;
[$column, $row] = Coordinate::indexesFromString($this->object->getEndCoordinates());
$c2 = $column - 1;
$r2 = $row - 1;
// end offsetX

View File

@ -527,11 +527,11 @@ class Parser
} elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_DEFINEDNAME . '$/mui', $token) && $this->spreadsheet->getDefinedName($token) !== null) {
return $this->convertDefinedName($token);
// commented so argument number can be processed correctly. See toReversePolish().
/*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/", $token))
{
return($this->convertFunction($token, $this->_func_args));
}*/
// if it's an argument, ignore the token (the argument remains)
/*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/", $token))
{
return($this->convertFunction($token, $this->_func_args));
}*/
// if it's an argument, ignore the token (the argument remains)
} elseif ($token == 'arg') {
return '';
}
@ -597,10 +597,9 @@ class Parser
if ($args >= 0) {
return pack('Cv', $this->ptg['ptgFuncV'], $this->functions[$token][0]);
}
// Variable number of args eg. SUM($i, $j, $k, ..).
if ($args == -1) {
return pack('CCv', $this->ptg['ptgFuncVarV'], $num_args, $this->functions[$token][0]);
}
return pack('CCv', $this->ptg['ptgFuncVarV'], $num_args, $this->functions[$token][0]);
}
/**
@ -852,10 +851,10 @@ class Parser
* called by the addWorksheet() method of the
* \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook class.
*
* @see \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook::addWorksheet()
*
* @param string $name The name of the worksheet being added
* @param int $index The index of the worksheet being added
*
* @see \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook::addWorksheet()
*/
public function setExtSheet($name, $index): void
{
@ -1231,9 +1230,9 @@ class Parser
* This function just introduces a ptgParen element in the tree, so that Excel
* doesn't get confused when working with a parenthesized formula afterwards.
*
* @see fact()
*
* @return array The parsed ptg'd tree
*
* @see fact()
*/
private function parenthesizedExpression()
{
@ -1475,6 +1474,7 @@ class Parser
} else {
$left_tree = '';
}
// add it's left subtree and return.
return $left_tree . $this->convertFunction($tree['value'], $tree['right']);
}

View File

@ -678,13 +678,13 @@ class Workbook extends BIFFwriter
$formulaData = '';
for ($j = 0; $j < $countPrintArea; ++$j) {
$printAreaRect = $printArea[$j]; // e.g. A3:J6
$printAreaRect[0] = Coordinate::coordinateFromString($printAreaRect[0]);
$printAreaRect[1] = Coordinate::coordinateFromString($printAreaRect[1]);
$printAreaRect[0] = Coordinate::indexesFromString($printAreaRect[0]);
$printAreaRect[1] = Coordinate::indexesFromString($printAreaRect[1]);
$print_rowmin = $printAreaRect[0][1] - 1;
$print_rowmax = $printAreaRect[1][1] - 1;
$print_colmin = Coordinate::columnIndexFromString($printAreaRect[0][0]) - 1;
$print_colmax = Coordinate::columnIndexFromString($printAreaRect[1][0]) - 1;
$print_colmin = $printAreaRect[0][0] - 1;
$print_colmax = $printAreaRect[1][0] - 1;
// construct formula data manually because parser does not recognize absolute 3d cell references
$formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax);
@ -756,7 +756,7 @@ class Workbook extends BIFFwriter
* Write a short NAME record.
*
* @param string $name
* @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global
* @param int $sheetIndex 1-based sheet index the defined name applies to. 0 = global
* @param int[][] $rangeBounds range boundaries
* @param bool $isHidden
*
@ -839,10 +839,9 @@ class Workbook extends BIFFwriter
/**
* Writes Excel BIFF BOUNDSHEET record.
*
* @param Worksheet $sheet Worksheet name
* @param int $offset Location of worksheet BOF
*/
private function writeBoundSheet($sheet, $offset): void
private function writeBoundSheet(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $sheet, $offset): void
{
$sheetname = $sheet->getTitle();
$record = 0x0085; // Record identifier

View File

@ -217,8 +217,8 @@ class Worksheet extends BIFFwriter
*
* @param int $str_total Total number of strings
* @param int $str_unique Total number of unique strings
* @param array &$str_table String Table
* @param array &$colors Colour Table
* @param array $str_table String Table
* @param array $colors Colour Table
* @param Parser $parser The formula parser created for the Workbook
* @param bool $preCalculateFormulas Flag indicating whether formulas should be calculated or just written
* @param \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $phpSheet The worksheet to write
@ -512,7 +512,7 @@ class Worksheet extends BIFFwriter
// Hyperlinks
foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) {
[$column, $row] = Coordinate::coordinateFromString($coordinate);
[$column, $row] = Coordinate::indexesFromString($coordinate);
$url = $hyperlink->getUrl();
@ -526,7 +526,7 @@ class Worksheet extends BIFFwriter
$url = 'external:' . $url;
}
$this->writeUrl($row - 1, Coordinate::columnIndexFromString($column) - 1, $url);
$this->writeUrl($row - 1, $column - 1, $url);
}
$this->writeDataValidity();
@ -587,10 +587,10 @@ class Worksheet extends BIFFwriter
$lastCell = $explodes[1];
}
$firstCellCoordinates = Coordinate::coordinateFromString($firstCell); // e.g. [0, 1]
$lastCellCoordinates = Coordinate::coordinateFromString($lastCell); // e.g. [1, 6]
$firstCellCoordinates = Coordinate::indexesFromString($firstCell); // e.g. [0, 1]
$lastCellCoordinates = Coordinate::indexesFromString($lastCell); // e.g. [1, 6]
return pack('vvvv', $firstCellCoordinates[1] - 1, $lastCellCoordinates[1] - 1, Coordinate::columnIndexFromString($firstCellCoordinates[0]) - 1, Coordinate::columnIndexFromString($lastCellCoordinates[0]) - 1);
return pack('vvvv', $firstCellCoordinates[1] - 1, $lastCellCoordinates[1] - 1, $firstCellCoordinates[0] - 1, $lastCellCoordinates[0] - 1);
}
/**
@ -1455,10 +1455,10 @@ class Worksheet extends BIFFwriter
// extract the row and column indexes
$range = Coordinate::splitRange($mergeCell);
[$first, $last] = $range[0];
[$firstColumn, $firstRow] = Coordinate::coordinateFromString($first);
[$lastColumn, $lastRow] = Coordinate::coordinateFromString($last);
[$firstColumn, $firstRow] = Coordinate::indexesFromString($first);
[$lastColumn, $lastRow] = Coordinate::indexesFromString($last);
$recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, Coordinate::columnIndexFromString($firstColumn) - 1, Coordinate::columnIndexFromString($lastColumn) - 1);
$recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, $firstColumn - 1, $lastColumn - 1);
// flush record if we have reached limit for number of merged cells, or reached final merged cell
if ($j == $maxCountMergeCellsPerRecord || $i == $countMergeCells) {
@ -1601,76 +1601,37 @@ class Worksheet extends BIFFwriter
*/
private function writePanes(): void
{
$panes = [];
if ($this->phpSheet->getFreezePane()) {
[$column, $row] = Coordinate::coordinateFromString($this->phpSheet->getFreezePane());
$panes[0] = Coordinate::columnIndexFromString($column) - 1;
$panes[1] = $row - 1;
[$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 {
if (!$this->phpSheet->getFreezePane()) {
// thaw panes
return;
}
$x = $panes[0] ?? null;
$y = $panes[1] ?? null;
$rwTop = $panes[2] ?? null;
$colLeft = $panes[3] ?? null;
if (count($panes) > 4) { // if Active pane was received
$pnnAct = $panes[4];
} else {
$pnnAct = null;
}
[$column, $row] = Coordinate::indexesFromString($this->phpSheet->getFreezePane());
$x = $column - 1;
$y = $row - 1;
[$leftMostColumn, $topRow] = Coordinate::indexesFromString($this->phpSheet->getTopLeftCell());
//Coordinates are zero-based in xls files
$rwTop = $topRow - 1;
$colLeft = $leftMostColumn - 1;
$record = 0x0041; // Record identifier
$length = 0x000A; // Number of bytes to follow
// Code specific to frozen or thawed panes.
if ($this->phpSheet->getFreezePane()) {
// Set default values for $rwTop and $colLeft
if (!isset($rwTop)) {
$rwTop = $y;
}
if (!$colLeft) {
$colLeft = $x;
}
} else {
// Set default values for $rwTop and $colLeft
if (!isset($rwTop)) {
$rwTop = 0;
}
if (!$colLeft) {
$colLeft = 0;
}
// Convert Excel's row and column units to the internal units.
// The default row height is 12.75
// The default column width is 8.43
// The following slope and intersection values were interpolated.
//
$y = 20 * $y + 255;
$x = 113.879 * $x + 390;
}
// Determine which pane should be active. There is also the undocumented
// option to override this should it be necessary: may be removed later.
//
if (!$pnnAct) {
if ($x != 0 && $y != 0) {
$pnnAct = 0; // Bottom right
}
if ($x != 0 && $y == 0) {
$pnnAct = 1; // Top right
}
if ($x == 0 && $y != 0) {
$pnnAct = 2; // Bottom left
}
if ($x == 0 && $y == 0) {
$pnnAct = 3; // Top left
}
$pnnAct = null;
if ($x != 0 && $y != 0) {
$pnnAct = 0; // Bottom right
}
if ($x != 0 && $y == 0) {
$pnnAct = 1; // Top right
}
if ($x == 0 && $y != 0) {
$pnnAct = 2; // Bottom left
}
if ($x == 0 && $y == 0) {
$pnnAct = 3; // Top left
}
$this->activePane = $pnnAct; // Used in writeSelection
@ -4427,10 +4388,7 @@ class Worksheet extends BIFFwriter
$arrConditional[] = $conditional->getHashCode();
}
// Cells
$arrCoord = Coordinate::coordinateFromString($cellCoordinate);
if (!is_numeric($arrCoord[0])) {
$arrCoord[0] = Coordinate::columnIndexFromString($arrCoord[0]);
}
$arrCoord = Coordinate::indexesFromString($cellCoordinate);
if ($numColumnMin === null || ($numColumnMin > $arrCoord[0])) {
$numColumnMin = $arrCoord[0];
}

View File

@ -5,8 +5,13 @@ namespace PhpOffice\PhpSpreadsheet\Writer;
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\HashTable;
use PhpOffice\PhpSpreadsheet\Shared\File;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Borders;
use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Font;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing as WorksheetDrawing;
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
@ -37,13 +42,6 @@ class Xlsx extends BaseWriter
*/
private $office2003compatibility = false;
/**
* Private writer parts.
*
* @var Xlsx\WriterPart[]
*/
private $writerParts = [];
/**
* Private Spreadsheet.
*
@ -61,49 +59,49 @@ class Xlsx extends BaseWriter
/**
* Private unique Conditional HashTable.
*
* @var HashTable
* @var HashTable<Conditional>
*/
private $stylesConditionalHashTable;
/**
* Private unique Style HashTable.
*
* @var HashTable
* @var HashTable<\PhpOffice\PhpSpreadsheet\Style\Style>
*/
private $styleHashTable;
/**
* Private unique Fill HashTable.
*
* @var HashTable
* @var HashTable<Fill>
*/
private $fillHashTable;
/**
* Private unique \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
*
* @var HashTable
* @var HashTable<Font>
*/
private $fontHashTable;
/**
* Private unique Borders HashTable.
*
* @var HashTable
* @var HashTable<Borders>
*/
private $bordersHashTable;
/**
* Private unique NumberFormat HashTable.
*
* @var HashTable
* @var HashTable<NumberFormat>
*/
private $numFmtHashTable;
/**
* Private unique \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
*
* @var HashTable
* @var HashTable<BaseDrawing>
*/
private $drawingHashTable;
@ -114,6 +112,71 @@ class Xlsx extends BaseWriter
*/
private $zip;
/**
* @var Chart
*/
private $writerPartChart;
/**
* @var Comments
*/
private $writerPartComments;
/**
* @var ContentTypes
*/
private $writerPartContentTypes;
/**
* @var DocProps
*/
private $writerPartDocProps;
/**
* @var Drawing
*/
private $writerPartDrawing;
/**
* @var Rels
*/
private $writerPartRels;
/**
* @var RelsRibbon
*/
private $writerPartRelsRibbon;
/**
* @var RelsVBA
*/
private $writerPartRelsVBA;
/**
* @var StringTable
*/
private $writerPartStringTable;
/**
* @var Style
*/
private $writerPartStyle;
/**
* @var Theme
*/
private $writerPartTheme;
/**
* @var Workbook
*/
private $writerPartWorkbook;
/**
* @var Worksheet
*/
private $writerPartWorksheet;
/**
* Create a new Xlsx Writer.
*/
@ -122,53 +185,93 @@ class Xlsx extends BaseWriter
// Assign PhpSpreadsheet
$this->setSpreadsheet($spreadsheet);
$writerPartsArray = [
'stringtable' => StringTable::class,
'contenttypes' => ContentTypes::class,
'docprops' => DocProps::class,
'rels' => Rels::class,
'theme' => Theme::class,
'style' => Style::class,
'workbook' => Workbook::class,
'worksheet' => Worksheet::class,
'drawing' => Drawing::class,
'comments' => Comments::class,
'chart' => Chart::class,
'relsvba' => RelsVBA::class,
'relsribbonobjects' => RelsRibbon::class,
];
// Initialise writer parts
// and Assign their parent IWriters
foreach ($writerPartsArray as $writer => $class) {
$this->writerParts[$writer] = new $class($this);
}
$hashTablesArray = ['stylesConditionalHashTable', 'fillHashTable', 'fontHashTable',
'bordersHashTable', 'numFmtHashTable', 'drawingHashTable',
'styleHashTable',
];
$this->writerPartChart = new Chart($this);
$this->writerPartComments = new Comments($this);
$this->writerPartContentTypes = new ContentTypes($this);
$this->writerPartDocProps = new DocProps($this);
$this->writerPartDrawing = new Drawing($this);
$this->writerPartRels = new Rels($this);
$this->writerPartRelsRibbon = new RelsRibbon($this);
$this->writerPartRelsVBA = new RelsVBA($this);
$this->writerPartStringTable = new StringTable($this);
$this->writerPartStyle = new Style($this);
$this->writerPartTheme = new Theme($this);
$this->writerPartWorkbook = new Workbook($this);
$this->writerPartWorksheet = new Worksheet($this);
// Set HashTable variables
foreach ($hashTablesArray as $tableName) {
$this->$tableName = new HashTable();
}
$this->bordersHashTable = new HashTable();
$this->drawingHashTable = new HashTable();
$this->fillHashTable = new HashTable();
$this->fontHashTable = new HashTable();
$this->numFmtHashTable = new HashTable();
$this->styleHashTable = new HashTable();
$this->stylesConditionalHashTable = new HashTable();
}
/**
* Get writer part.
*
* @param string $pPartName Writer part name
*
* @return \PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart
*/
public function getWriterPart($pPartName)
public function getWriterPartChart(): Chart
{
if ($pPartName != '' && isset($this->writerParts[strtolower($pPartName)])) {
return $this->writerParts[strtolower($pPartName)];
}
return $this->writerPartChart;
}
return null;
public function getWriterPartComments(): Comments
{
return $this->writerPartComments;
}
public function getWriterPartContentTypes(): ContentTypes
{
return $this->writerPartContentTypes;
}
public function getWriterPartDocProps(): DocProps
{
return $this->writerPartDocProps;
}
public function getWriterPartDrawing(): Drawing
{
return $this->writerPartDrawing;
}
public function getWriterPartRels(): Rels
{
return $this->writerPartRels;
}
public function getWriterPartRelsRibbon(): RelsRibbon
{
return $this->writerPartRelsRibbon;
}
public function getWriterPartRelsVBA(): RelsVBA
{
return $this->writerPartRelsVBA;
}
public function getWriterPartStringTable(): StringTable
{
return $this->writerPartStringTable;
}
public function getWriterPartStyle(): Style
{
return $this->writerPartStyle;
}
public function getWriterPartTheme(): Theme
{
return $this->writerPartTheme;
}
public function getWriterPartWorkbook(): Workbook
{
return $this->writerPartWorkbook;
}
public function getWriterPartWorksheet(): Worksheet
{
return $this->writerPartWorksheet;
}
/**
@ -192,19 +295,19 @@ class Xlsx extends BaseWriter
// Create string lookup table
$this->stringTable = [];
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
$this->stringTable = $this->getWriterPart('StringTable')->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
$this->stringTable = $this->getWriterPartStringTable()->createStringTable($this->spreadSheet->getSheet($i), $this->stringTable);
}
// Create styles dictionaries
$this->styleHashTable->addFromSource($this->getWriterPart('Style')->allStyles($this->spreadSheet));
$this->stylesConditionalHashTable->addFromSource($this->getWriterPart('Style')->allConditionalStyles($this->spreadSheet));
$this->fillHashTable->addFromSource($this->getWriterPart('Style')->allFills($this->spreadSheet));
$this->fontHashTable->addFromSource($this->getWriterPart('Style')->allFonts($this->spreadSheet));
$this->bordersHashTable->addFromSource($this->getWriterPart('Style')->allBorders($this->spreadSheet));
$this->numFmtHashTable->addFromSource($this->getWriterPart('Style')->allNumberFormats($this->spreadSheet));
$this->styleHashTable->addFromSource($this->getWriterPartStyle()->allStyles($this->spreadSheet));
$this->stylesConditionalHashTable->addFromSource($this->getWriterPartStyle()->allConditionalStyles($this->spreadSheet));
$this->fillHashTable->addFromSource($this->getWriterPartStyle()->allFills($this->spreadSheet));
$this->fontHashTable->addFromSource($this->getWriterPartStyle()->allFonts($this->spreadSheet));
$this->bordersHashTable->addFromSource($this->getWriterPartStyle()->allBorders($this->spreadSheet));
$this->numFmtHashTable->addFromSource($this->getWriterPartStyle()->allNumberFormats($this->spreadSheet));
// Create drawing dictionary
$this->drawingHashTable->addFromSource($this->getWriterPart('Drawing')->allDrawings($this->spreadSheet));
$this->drawingHashTable->addFromSource($this->getWriterPartDrawing()->allDrawings($this->spreadSheet));
$options = new Archive();
$options->setEnableZip64(false);
@ -213,7 +316,7 @@ class Xlsx extends BaseWriter
$this->zip = new ZipStream(null, $options);
// Add [Content_Types].xml to ZIP file
$this->addZipFile('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->spreadSheet, $this->includeCharts));
$this->addZipFile('[Content_Types].xml', $this->getWriterPartContentTypes()->writeContentTypes($this->spreadSheet, $this->includeCharts));
//if hasMacros, add the vbaProject.bin file, Certificate file(if exists)
if ($this->spreadSheet->hasMacros()) {
@ -225,7 +328,7 @@ class Xlsx extends BaseWriter
//signed macros ?
// Yes : add the certificate file and the related rels file
$this->addZipFile('xl/vbaProjectSignature.bin', $this->spreadSheet->getMacrosCertificate());
$this->addZipFile('xl/_rels/vbaProject.bin.rels', $this->getWriterPart('RelsVBA')->writeVBARelationships($this->spreadSheet));
$this->addZipFile('xl/_rels/vbaProject.bin.rels', $this->getWriterPartRelsVBA()->writeVBARelationships($this->spreadSheet));
}
}
}
@ -240,43 +343,43 @@ class Xlsx extends BaseWriter
$this->addZipFile($tmpRootPath . $aPath, $aContent);
}
//the rels for files
$this->addZipFile($tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels', $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->spreadSheet));
$this->addZipFile($tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels', $this->getWriterPartRelsRibbon()->writeRibbonRelationships($this->spreadSheet));
}
}
// Add relationships to ZIP file
$this->addZipFile('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->spreadSheet));
$this->addZipFile('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->spreadSheet));
$this->addZipFile('_rels/.rels', $this->getWriterPartRels()->writeRelationships($this->spreadSheet));
$this->addZipFile('xl/_rels/workbook.xml.rels', $this->getWriterPartRels()->writeWorkbookRelationships($this->spreadSheet));
// Add document properties to ZIP file
$this->addZipFile('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->spreadSheet));
$this->addZipFile('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->spreadSheet));
$customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->spreadSheet);
$this->addZipFile('docProps/app.xml', $this->getWriterPartDocProps()->writeDocPropsApp($this->spreadSheet));
$this->addZipFile('docProps/core.xml', $this->getWriterPartDocProps()->writeDocPropsCore($this->spreadSheet));
$customPropertiesPart = $this->getWriterPartDocProps()->writeDocPropsCustom($this->spreadSheet);
if ($customPropertiesPart !== null) {
$this->addZipFile('docProps/custom.xml', $customPropertiesPart);
}
// Add theme to ZIP file
$this->addZipFile('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->spreadSheet));
$this->addZipFile('xl/theme/theme1.xml', $this->getWriterPartTheme()->writeTheme($this->spreadSheet));
// Add string table to ZIP file
$this->addZipFile('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->stringTable));
$this->addZipFile('xl/sharedStrings.xml', $this->getWriterPartStringTable()->writeStringTable($this->stringTable));
// Add styles to ZIP file
$this->addZipFile('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->spreadSheet));
$this->addZipFile('xl/styles.xml', $this->getWriterPartStyle()->writeStyles($this->spreadSheet));
// Add workbook to ZIP file
$this->addZipFile('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas));
$this->addZipFile('xl/workbook.xml', $this->getWriterPartWorkbook()->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas));
$chartCount = 0;
// Add worksheets
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
$this->addZipFile('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts));
$this->addZipFile('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPartWorksheet()->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts));
if ($this->includeCharts) {
$charts = $this->spreadSheet->getSheet($i)->getChartCollection();
if (count($charts) > 0) {
foreach ($charts as $chart) {
$this->addZipFile('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart, $this->preCalculateFormulas));
$this->addZipFile('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPartChart()->writeChart($chart, $this->preCalculateFormulas));
++$chartCount;
}
}
@ -287,7 +390,7 @@ class Xlsx extends BaseWriter
// Add worksheet relationships (drawings, ...)
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
// Add relationships
$this->addZipFile('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
$this->addZipFile('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPartRels()->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
// Add unparsedLoadedData
$sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName();
@ -312,13 +415,13 @@ class Xlsx extends BaseWriter
// Add drawing and image relationship parts
if (($drawingCount > 0) || ($chartCount > 0)) {
// Drawing relationships
$this->addZipFile('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts));
$this->addZipFile('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPartRels()->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts));
// Drawings
$this->addZipFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
$this->addZipFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
} elseif (isset($unparsedLoadedData['sheets'][$sheetCodeName]['drawingAlternateContents'])) {
// Drawings
$this->addZipFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
$this->addZipFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPartDrawing()->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
}
// Add unparsed drawings
@ -335,10 +438,10 @@ class Xlsx extends BaseWriter
// Add comment relationship parts
if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
// VML Comments
$this->addZipFile('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->spreadSheet->getSheet($i)));
$this->addZipFile('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPartComments()->writeVMLComments($this->spreadSheet->getSheet($i)));
// Comments
$this->addZipFile('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->spreadSheet->getSheet($i)));
$this->addZipFile('xl/comments' . ($i + 1) . '.xml', $this->getWriterPartComments()->writeComments($this->spreadSheet->getSheet($i)));
}
// Add unparsed relationship parts
@ -351,10 +454,10 @@ class Xlsx extends BaseWriter
// Add header/footer relationship parts
if (count($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
// VML Drawings
$this->addZipFile('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)));
$this->addZipFile('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPartDrawing()->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)));
// VML Drawing relationships
$this->addZipFile('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)));
$this->addZipFile('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPartRels()->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)));
// Media
foreach ($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
@ -445,7 +548,7 @@ class Xlsx extends BaseWriter
/**
* Get Style HashTable.
*
* @return HashTable
* @return HashTable<\PhpOffice\PhpSpreadsheet\Style\Style>
*/
public function getStyleHashTable()
{
@ -455,7 +558,7 @@ class Xlsx extends BaseWriter
/**
* Get Conditional HashTable.
*
* @return HashTable
* @return HashTable<Conditional>
*/
public function getStylesConditionalHashTable()
{
@ -465,7 +568,7 @@ class Xlsx extends BaseWriter
/**
* Get Fill HashTable.
*
* @return HashTable
* @return HashTable<Fill>
*/
public function getFillHashTable()
{
@ -475,7 +578,7 @@ class Xlsx extends BaseWriter
/**
* Get \PhpOffice\PhpSpreadsheet\Style\Font HashTable.
*
* @return HashTable
* @return HashTable<Font>
*/
public function getFontHashTable()
{
@ -485,7 +588,7 @@ class Xlsx extends BaseWriter
/**
* Get Borders HashTable.
*
* @return HashTable
* @return HashTable<Borders>
*/
public function getBordersHashTable()
{
@ -495,7 +598,7 @@ class Xlsx extends BaseWriter
/**
* Get NumberFormat HashTable.
*
* @return HashTable
* @return HashTable<NumberFormat>
*/
public function getNumFmtHashTable()
{
@ -505,7 +608,7 @@ class Xlsx extends BaseWriter
/**
* Get \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\BaseDrawing HashTable.
*
* @return HashTable
* @return HashTable<BaseDrawing>
*/
public function getDrawingHashTable()
{

View File

@ -129,7 +129,7 @@ class Chart extends WriterPart
if ((is_array($caption)) && (count($caption) > 0)) {
$caption = $caption[0];
}
$this->getParentWriter()->getWriterPart('stringtable')->writeRichTextForCharts($objWriter, $caption, 'a');
$this->getParentWriter()->getWriterPartstringtable()->writeRichTextForCharts($objWriter, $caption, 'a');
$objWriter->endElement();
$objWriter->endElement();
@ -1040,9 +1040,9 @@ class Chart extends WriterPart
* @param DataSeries $plotGroup
* @param string $groupType Type of plot for dataseries
* @param XMLWriter $objWriter XML Writer
* @param bool &$catIsMultiLevelSeries Is category a multi-series category
* @param bool &$valIsMultiLevelSeries Is value set a multi-series set
* @param string &$plotGroupingType Type of grouping for multi-series values
* @param bool $catIsMultiLevelSeries Is category a multi-series category
* @param bool $valIsMultiLevelSeries Is value set a multi-series set
* @param string $plotGroupingType Type of grouping for multi-series values
*/
private function writePlotGroup($plotGroup, $groupType, $objWriter, &$catIsMultiLevelSeries, &$valIsMultiLevelSeries, &$plotGroupingType): void
{

View File

@ -79,7 +79,7 @@ class Comments extends WriterPart
// text
$objWriter->startElement('text');
$this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText());
$this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $pComment->getText());
$objWriter->endElement();
$objWriter->endElement();
@ -165,8 +165,7 @@ class Comments extends WriterPart
private function writeVMLComment(XMLWriter $objWriter, $pCellReference, Comment $pComment): void
{
// Metadata
[$column, $row] = Coordinate::coordinateFromString($pCellReference);
$column = Coordinate::columnIndexFromString($column);
[$column, $row] = Coordinate::indexesFromString($pCellReference);
$id = 1024 + $column + $row;
$id = substr($id, 0, 4);

View File

@ -84,22 +84,22 @@ class Drawing extends WriterPart
public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $pChart, $pRelationId = -1): void
{
$tl = $pChart->getTopLeftPosition();
$tl['colRow'] = Coordinate::coordinateFromString($tl['cell']);
$tlColRow = Coordinate::indexesFromString($tl['cell']);
$br = $pChart->getBottomRightPosition();
$br['colRow'] = Coordinate::coordinateFromString($br['cell']);
$brColRow = Coordinate::indexesFromString($br['cell']);
$objWriter->startElement('xdr:twoCellAnchor');
$objWriter->startElement('xdr:from');
$objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($tl['colRow'][0]) - 1);
$objWriter->writeElement('xdr:col', $tlColRow[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['xOffset']));
$objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1);
$objWriter->writeElement('xdr:row', $tlColRow[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($tl['yOffset']));
$objWriter->endElement();
$objWriter->startElement('xdr:to');
$objWriter->writeElement('xdr:col', Coordinate::columnIndexFromString($br['colRow'][0]) - 1);
$objWriter->writeElement('xdr:col', $brColRow[0] - 1);
$objWriter->writeElement('xdr:colOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['xOffset']));
$objWriter->writeElement('xdr:row', $br['colRow'][1] - 1);
$objWriter->writeElement('xdr:row', $brColRow[1] - 1);
$objWriter->writeElement('xdr:rowOff', \PhpOffice\PhpSpreadsheet\Shared\Drawing::pixelsToEMU($br['yOffset']));
$objWriter->endElement();
@ -158,8 +158,7 @@ class Drawing extends WriterPart
// xdr:oneCellAnchor
$objWriter->startElement('xdr:oneCellAnchor');
// Image location
$aCoordinates = Coordinate::coordinateFromString($pDrawing->getCoordinates());
$aCoordinates[0] = Coordinate::columnIndexFromString($aCoordinates[0]);
$aCoordinates = Coordinate::indexesFromString($pDrawing->getCoordinates());
// xdr:from
$objWriter->startElement('xdr:from');
@ -433,7 +432,7 @@ class Drawing extends WriterPart
{
// Calculate object id
preg_match('{(\d+)}', md5($pReference), $m);
$id = 1500 + (substr($m[1], 0, 2) * 1);
$id = 1500 + ((int) substr($m[1], 0, 2) * 1);
// Calculate offset
$width = $pImage->getWidth();

View File

@ -291,7 +291,7 @@ class Rels extends WriterPart
/**
* Write drawing relationships to XML format.
*
* @param int &$chartRef Chart ID
* @param int $chartRef Chart ID
* @param bool $includeCharts Flag indicating if we should write charts
*
* @return string XML Output
@ -425,9 +425,7 @@ class Rels extends WriterPart
}
/**
* @param $objWriter
* @param \PhpOffice\PhpSpreadsheet\Worksheet\Drawing $drawing
* @param $i
*
* @return int
*/

View File

@ -784,13 +784,9 @@ class Theme extends WriterPart
/**
* Write fonts to XML format.
*
* @param XMLWriter $objWriter
* @param string $latinFont
* @param array of string $fontSet
*
* @return string XML Output
* @param string[] $fontSet
*/
private function writeFonts($objWriter, $latinFont, $fontSet)
private function writeFonts(XMLWriter $objWriter, string $latinFont, array $fontSet): void
{
// a:latin
$objWriter->startElement('a:latin');
@ -817,12 +813,8 @@ class Theme extends WriterPart
/**
* Write colour scheme to XML format.
*
* @param XMLWriter $objWriter
*
* @return string XML Output
*/
private function writeColourScheme($objWriter)
private function writeColourScheme(XMLWriter $objWriter): void
{
foreach (self::$colourScheme as $colourName => $colourValue) {
$objWriter->startElement('a:' . $colourName);

View File

@ -1084,7 +1084,7 @@ class Worksheet extends WriterPart
private function writeSheetData(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet, array $pStringTable): void
{
// Flipped stringtable, for faster index searching
$aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable);
$aFlippedStringTable = $this->getParentWriter()->getWriterPartstringtable()->flipStringTable($pStringTable);
// sheetData
$objWriter->startElement('sheetData');
@ -1169,7 +1169,7 @@ class Worksheet extends WriterPart
$objWriter->writeElement('t', StringHelper::controlCharacterPHP2OOXML(htmlspecialchars($cellValue)));
} elseif ($cellValue instanceof RichText) {
$objWriter->startElement('is');
$this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue);
$this->getParentWriter()->getWriterPartstringtable()->writeRichText($objWriter, $cellValue);
$objWriter->endElement();
}
}

View File

@ -262,9 +262,6 @@ class AdvancedValueBinderTest extends TestCase
/**
* @dataProvider stringProvider
*
* @param mixed $value
* @param mixed $wrapped
*/
public function testStringWrapping(string $value, bool $wrapped): void
{

View File

@ -96,6 +96,20 @@ class CoordinateTest extends TestCase
return require 'tests/data/CellCoordinates.php';
}
/**
* @dataProvider providerIndexesFromString
*/
public function testIndexesFromString(array $expectedResult, string $rangeSet): void
{
$result = Coordinate::indexesFromString($rangeSet);
self::assertSame($expectedResult, $result);
}
public function providerIndexesFromString(): array
{
return require 'tests/data/Cell/IndexesFromString.php';
}
public function testCoordinateFromStringWithRangeAddress(): void
{
$cellAddress = 'A1:AI2012';

View File

@ -8,6 +8,7 @@ use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder;
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class DefaultValueBinderTest extends TestCase
@ -15,7 +16,7 @@ class DefaultValueBinderTest extends TestCase
private function createCellStub()
{
// Create a stub for the Cell class.
/** @var Cell $cellStub */
/** @var Cell&MockObject $cellStub */
$cellStub = $this->getMockBuilder(Cell::class)
->disableOriginalConstructor()
->getMock();

View File

@ -135,6 +135,7 @@ class DefinedNameTest extends TestCase
DefinedName::createInstance('xyz', $this->spreadsheet->getActiveSheet(), 'A1')
);
/** @var NamedRange $namedRange */
$namedRange = $this->spreadsheet->getDefinedName('XYZ');
self::assertInstanceOf(NamedRange::class, $namedRange);
self::assertEquals('A1', $namedRange->getRange());

View File

@ -15,8 +15,6 @@ class ColumnWidthTest extends AbstractFunctional
/**
* @dataProvider providerFormats
*
* @param $format
*/
public function testReadColumnWidth($format): void
{

View File

@ -21,8 +21,6 @@ class CommentsTest extends AbstractFunctional
* count of comments in correct coords.
*
* @dataProvider providerFormats
*
* @param $format
*/
public function testComments($format): void
{

View File

@ -23,8 +23,8 @@ class CsvContiguousTest extends TestCase
// Tell the Reader that we want to use the Read Filter that we've Instantiated
// and that we want to store it in contiguous rows/columns
self::assertFalse($reader->getContiguous());
$reader->setReadFilter($chunkFilter)
->setContiguous(true);
$reader->setReadFilter($chunkFilter);
$reader->setContiguous(true);
// Instantiate a new PhpSpreadsheet object manually
$spreadsheet = new Spreadsheet();
@ -65,8 +65,8 @@ class CsvContiguousTest extends TestCase
// Tell the Reader that we want to use the Read Filter that we've Instantiated
// and that we want to store it in contiguous rows/columns
$reader->setReadFilter($chunkFilter)
->setContiguous(true);
$reader->setReadFilter($chunkFilter);
$reader->setContiguous(true);
// Instantiate a new PhpSpreadsheet object manually
$spreadsheet = new Spreadsheet();

View File

@ -23,7 +23,6 @@ class XmlScannerTest extends TestCase
*
* @param mixed $filename
* @param mixed $expectedResult
* @param $libxmlDisableEntityLoader
*/
public function testValidXML($filename, $expectedResult, $libxmlDisableEntityLoader): void
{
@ -59,7 +58,6 @@ class XmlScannerTest extends TestCase
* @dataProvider providerInvalidXML
*
* @param mixed $filename
* @param $libxmlDisableEntityLoader
*/
public function testInvalidXML($filename, $libxmlDisableEntityLoader): void
{

View File

@ -250,7 +250,6 @@ class XlsxTest extends TestCase
* Test if all whitespace is removed from a style definition string.
* This is needed to parse it into properties with the correct keys.
*
* @param $string
* @dataProvider providerStripsWhiteSpaceFromStyleString
*/
public function testStripsWhiteSpaceFromStyleString($string): void

View File

@ -10,8 +10,6 @@ class XmlTest extends TestCase
{
/**
* @dataProvider providerInvalidSimpleXML
*
* @param $filename
*/
public function testInvalidSimpleXML($filename): void
{

View File

@ -44,9 +44,6 @@ class SpreadsheetTest extends TestCase
}
/**
* @param $index
* @param $sheetName
*
* @dataProvider dataProviderForSheetNames
*/
public function testGetSheetByName($index, $sheetName): void

View File

@ -0,0 +1,74 @@
<?php
return [
[
[
1,
1,
],
'A1',
],
[
[
1,
12,
],
'A12',
],
[
[
10,
1,
],
'J1',
],
[
[
10,
20,
],
'J20',
],
[
[
35,
1,
],
'AI1',
],
[
[
35,
2012,
],
'AI2012',
],
[
[
2,
3,
],
'B3',
],
[
[
2,
3,
],
'$B3',
],
[
[
2,
3,
],
'B$3',
],
[
[
2,
3,
],
'$B$3',
],
];

View File

@ -43,4 +43,32 @@ return [
],
'AI2012',
],
[
[
'B',
3,
],
'B3',
],
[
[
'$B',
3,
],
'$B3',
],
[
[
'B',
'$3',
],
'B$3',
],
[
[
'$B',
'$3',
],
'$B$3',
],
];