package and depencies
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ class Column
|
||||
/**
|
||||
* Autofilter.
|
||||
*
|
||||
* @var AutoFilter
|
||||
* @var null|AutoFilter
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
@@ -77,27 +77,34 @@ class Column
|
||||
/**
|
||||
* Autofilter Column Rules.
|
||||
*
|
||||
* @var array of Column\Rule
|
||||
* @var Column\Rule[]
|
||||
*/
|
||||
private $ruleset = [];
|
||||
|
||||
/**
|
||||
* Autofilter Column Dynamic Attributes.
|
||||
*
|
||||
* @var array of mixed
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $attributes = [];
|
||||
|
||||
/**
|
||||
* Create a new Column.
|
||||
*
|
||||
* @param string $pColumn Column (e.g. A)
|
||||
* @param AutoFilter $pParent Autofilter for this column
|
||||
* @param string $column Column (e.g. A)
|
||||
* @param AutoFilter $parent Autofilter for this column
|
||||
*/
|
||||
public function __construct($pColumn, ?AutoFilter $pParent = null)
|
||||
public function __construct($column, ?AutoFilter $parent = null)
|
||||
{
|
||||
$this->columnIndex = $pColumn;
|
||||
$this->parent = $pParent;
|
||||
$this->columnIndex = $column;
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
public function setEvaluatedFalse(): void
|
||||
{
|
||||
if ($this->parent !== null) {
|
||||
$this->parent->setEvaluated(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,19 +120,20 @@ class Column
|
||||
/**
|
||||
* Set AutoFilter column index as string eg: 'A'.
|
||||
*
|
||||
* @param string $pColumn Column (e.g. A)
|
||||
* @param string $column Column (e.g. A)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnIndex($pColumn)
|
||||
public function setColumnIndex($column)
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
// Uppercase coordinate
|
||||
$pColumn = strtoupper($pColumn);
|
||||
$column = strtoupper($column);
|
||||
if ($this->parent !== null) {
|
||||
$this->parent->testColumnInRange($pColumn);
|
||||
$this->parent->testColumnInRange($column);
|
||||
}
|
||||
|
||||
$this->columnIndex = $pColumn;
|
||||
$this->columnIndex = $column;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -133,7 +141,7 @@ class Column
|
||||
/**
|
||||
* Get this Column's AutoFilter Parent.
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return null|AutoFilter
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
@@ -143,13 +151,12 @@ class Column
|
||||
/**
|
||||
* Set this Column's AutoFilter Parent.
|
||||
*
|
||||
* @param AutoFilter $pParent
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(?AutoFilter $pParent = null)
|
||||
public function setParent(?AutoFilter $parent = null)
|
||||
{
|
||||
$this->parent = $pParent;
|
||||
$this->setEvaluatedFalse();
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -167,17 +174,21 @@ class Column
|
||||
/**
|
||||
* Set AutoFilter Type.
|
||||
*
|
||||
* @param string $pFilterType
|
||||
* @param string $filterType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFilterType($pFilterType)
|
||||
public function setFilterType($filterType)
|
||||
{
|
||||
if (!in_array($pFilterType, self::$filterTypes)) {
|
||||
$this->setEvaluatedFalse();
|
||||
if (!in_array($filterType, self::$filterTypes)) {
|
||||
throw new PhpSpreadsheetException('Invalid filter type for column AutoFilter.');
|
||||
}
|
||||
if ($filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) > 2) {
|
||||
throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
|
||||
}
|
||||
|
||||
$this->filterType = $pFilterType;
|
||||
$this->filterType = $filterType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -195,19 +206,20 @@ class Column
|
||||
/**
|
||||
* Set AutoFilter Multiple Rules And/Or.
|
||||
*
|
||||
* @param string $pJoin And/Or
|
||||
* @param string $join And/Or
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setJoin($pJoin)
|
||||
public function setJoin($join)
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
// Lowercase And/Or
|
||||
$pJoin = strtolower($pJoin);
|
||||
if (!in_array($pJoin, self::$ruleJoins)) {
|
||||
$join = strtolower($join);
|
||||
if (!in_array($join, self::$ruleJoins)) {
|
||||
throw new PhpSpreadsheetException('Invalid rule connection for column AutoFilter.');
|
||||
}
|
||||
|
||||
$this->join = $pJoin;
|
||||
$this->join = $join;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -215,12 +227,13 @@ class Column
|
||||
/**
|
||||
* Set AutoFilter Attributes.
|
||||
*
|
||||
* @param string[] $attributes
|
||||
* @param mixed[] $attributes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttributes(array $attributes)
|
||||
public function setAttributes($attributes)
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
$this->attributes = $attributes;
|
||||
|
||||
return $this;
|
||||
@@ -229,14 +242,15 @@ class Column
|
||||
/**
|
||||
* Set An AutoFilter Attribute.
|
||||
*
|
||||
* @param string $pName Attribute Name
|
||||
* @param string $pValue Attribute Value
|
||||
* @param string $name Attribute Name
|
||||
* @param int|string $value Attribute Value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute($pName, $pValue)
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
$this->attributes[$pName] = $pValue;
|
||||
$this->setEvaluatedFalse();
|
||||
$this->attributes[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -244,7 +258,7 @@ class Column
|
||||
/**
|
||||
* Get AutoFilter Column Attributes.
|
||||
*
|
||||
* @return string[]
|
||||
* @return int[]|string[]
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
@@ -254,19 +268,24 @@ class Column
|
||||
/**
|
||||
* Get specific AutoFilter Column Attribute.
|
||||
*
|
||||
* @param string $pName Attribute Name
|
||||
* @param string $name Attribute Name
|
||||
*
|
||||
* @return string
|
||||
* @return null|int|string
|
||||
*/
|
||||
public function getAttribute($pName)
|
||||
public function getAttribute($name)
|
||||
{
|
||||
if (isset($this->attributes[$pName])) {
|
||||
return $this->attributes[$pName];
|
||||
if (isset($this->attributes[$name])) {
|
||||
return $this->attributes[$name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function ruleCount(): int
|
||||
{
|
||||
return count($this->ruleset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all AutoFilter Column Rules.
|
||||
*
|
||||
@@ -280,17 +299,17 @@ class Column
|
||||
/**
|
||||
* Get a specified AutoFilter Column Rule.
|
||||
*
|
||||
* @param int $pIndex Rule index in the ruleset array
|
||||
* @param int $index Rule index in the ruleset array
|
||||
*
|
||||
* @return Column\Rule
|
||||
*/
|
||||
public function getRule($pIndex)
|
||||
public function getRule($index)
|
||||
{
|
||||
if (!isset($this->ruleset[$pIndex])) {
|
||||
$this->ruleset[$pIndex] = new Column\Rule($this);
|
||||
if (!isset($this->ruleset[$index])) {
|
||||
$this->ruleset[$index] = new Column\Rule($this);
|
||||
}
|
||||
|
||||
return $this->ruleset[$pIndex];
|
||||
return $this->ruleset[$index];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,6 +319,10 @@ class Column
|
||||
*/
|
||||
public function createRule()
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
if ($this->filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) >= 2) {
|
||||
throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
|
||||
}
|
||||
$this->ruleset[] = new Column\Rule($this);
|
||||
|
||||
return end($this->ruleset);
|
||||
@@ -310,10 +333,11 @@ class Column
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addRule(Column\Rule $pRule)
|
||||
public function addRule(Column\Rule $rule)
|
||||
{
|
||||
$pRule->setParent($this);
|
||||
$this->ruleset[] = $pRule;
|
||||
$this->setEvaluatedFalse();
|
||||
$rule->setParent($this);
|
||||
$this->ruleset[] = $rule;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -322,14 +346,15 @@ class Column
|
||||
* Delete a specified AutoFilter Column Rule
|
||||
* If the number of rules is reduced to 1, then we reset And/Or logic to Or.
|
||||
*
|
||||
* @param int $pIndex Rule index in the ruleset array
|
||||
* @param int $index Rule index in the ruleset array
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function deleteRule($pIndex)
|
||||
public function deleteRule($index)
|
||||
{
|
||||
if (isset($this->ruleset[$pIndex])) {
|
||||
unset($this->ruleset[$pIndex]);
|
||||
$this->setEvaluatedFalse();
|
||||
if (isset($this->ruleset[$index])) {
|
||||
unset($this->ruleset[$index]);
|
||||
// If we've just deleted down to a single rule, then reset And/Or joining to Or
|
||||
if (count($this->ruleset) <= 1) {
|
||||
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
|
||||
@@ -346,6 +371,7 @@ class Column
|
||||
*/
|
||||
public function clearRules()
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
$this->ruleset = [];
|
||||
$this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
|
||||
|
||||
@@ -370,8 +396,6 @@ class Column
|
||||
$cloned->setParent($this); // attach the new cloned Rule to this new cloned Autofilter Cloned object
|
||||
$this->ruleset[$k] = $cloned;
|
||||
}
|
||||
} elseif (is_object($value)) {
|
||||
$this->$key = clone $value;
|
||||
} else {
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ class Rule
|
||||
const AUTOFILTER_RULETYPE_DYNAMICFILTER = 'dynamicFilter';
|
||||
const AUTOFILTER_RULETYPE_TOPTENFILTER = 'top10Filter';
|
||||
|
||||
private static $ruleTypes = [
|
||||
private const RULE_TYPES = [
|
||||
// Currently we're not handling
|
||||
// colorFilter
|
||||
// extLst
|
||||
@@ -32,7 +32,7 @@ class Rule
|
||||
const AUTOFILTER_RULETYPE_DATEGROUP_MINUTE = 'minute';
|
||||
const AUTOFILTER_RULETYPE_DATEGROUP_SECOND = 'second';
|
||||
|
||||
private static $dateTimeGroups = [
|
||||
private const DATE_TIME_GROUPS = [
|
||||
self::AUTOFILTER_RULETYPE_DATEGROUP_YEAR,
|
||||
self::AUTOFILTER_RULETYPE_DATEGROUP_MONTH,
|
||||
self::AUTOFILTER_RULETYPE_DATEGROUP_DAY,
|
||||
@@ -88,7 +88,7 @@ class Rule
|
||||
const AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE = 'aboveAverage';
|
||||
const AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE = 'belowAverage';
|
||||
|
||||
private static $dynamicTypes = [
|
||||
private const DYNAMIC_TYPES = [
|
||||
self::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY,
|
||||
self::AUTOFILTER_RULETYPE_DYNAMIC_TODAY,
|
||||
self::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW,
|
||||
@@ -125,15 +125,7 @@ class Rule
|
||||
self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE,
|
||||
];
|
||||
|
||||
/*
|
||||
* The only valid filter rule operators for filter and customFilter types are:
|
||||
* <xsd:enumeration value="equal"/>
|
||||
* <xsd:enumeration value="lessThan"/>
|
||||
* <xsd:enumeration value="lessThanOrEqual"/>
|
||||
* <xsd:enumeration value="notEqual"/>
|
||||
* <xsd:enumeration value="greaterThanOrEqual"/>
|
||||
* <xsd:enumeration value="greaterThan"/>
|
||||
*/
|
||||
// Filter rule operators for filter and customFilter types.
|
||||
const AUTOFILTER_COLUMN_RULE_EQUAL = 'equal';
|
||||
const AUTOFILTER_COLUMN_RULE_NOTEQUAL = 'notEqual';
|
||||
const AUTOFILTER_COLUMN_RULE_GREATERTHAN = 'greaterThan';
|
||||
@@ -141,7 +133,7 @@ class Rule
|
||||
const AUTOFILTER_COLUMN_RULE_LESSTHAN = 'lessThan';
|
||||
const AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL = 'lessThanOrEqual';
|
||||
|
||||
private static $operators = [
|
||||
private const OPERATORS = [
|
||||
self::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
self::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
|
||||
self::AUTOFILTER_COLUMN_RULE_GREATERTHAN,
|
||||
@@ -153,7 +145,7 @@ class Rule
|
||||
const AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE = 'byValue';
|
||||
const AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT = 'byPercent';
|
||||
|
||||
private static $topTenValue = [
|
||||
private const TOP_TEN_VALUE = [
|
||||
self::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE,
|
||||
self::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT,
|
||||
];
|
||||
@@ -161,49 +153,27 @@ class Rule
|
||||
const AUTOFILTER_COLUMN_RULE_TOPTEN_TOP = 'top';
|
||||
const AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM = 'bottom';
|
||||
|
||||
private static $topTenType = [
|
||||
private const TOP_TEN_TYPE = [
|
||||
self::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP,
|
||||
self::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM,
|
||||
];
|
||||
|
||||
// Rule Operators (Numeric, Boolean etc)
|
||||
// const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
|
||||
// Unimplented Rule Operators (Numeric, Boolean etc)
|
||||
// const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
|
||||
// Rule Operators (Numeric Special) which are translated to standard numeric operators with calculated values
|
||||
// const AUTOFILTER_COLUMN_RULE_TOPTEN = 'topTen'; // greaterThan calculated value
|
||||
// const AUTOFILTER_COLUMN_RULE_TOPTENPERCENT = 'topTenPercent'; // greaterThan calculated value
|
||||
// const AUTOFILTER_COLUMN_RULE_ABOVEAVERAGE = 'aboveAverage'; // Value is calculated as the average
|
||||
// const AUTOFILTER_COLUMN_RULE_BELOWAVERAGE = 'belowAverage'; // Value is calculated as the average
|
||||
// Rule Operators (String) which are set as wild-carded values
|
||||
// const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
|
||||
// const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
|
||||
// const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
|
||||
// const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
|
||||
// const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
|
||||
// const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
|
||||
// const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
|
||||
// const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
|
||||
// Rule Operators (Date Special) which are translated to standard numeric operators with calculated values
|
||||
// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
|
||||
// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
|
||||
// const AUTOFILTER_COLUMN_RULE_YESTERDAY = 'yesterday';
|
||||
// const AUTOFILTER_COLUMN_RULE_TODAY = 'today';
|
||||
// const AUTOFILTER_COLUMN_RULE_TOMORROW = 'tomorrow';
|
||||
// const AUTOFILTER_COLUMN_RULE_LASTWEEK = 'lastWeek';
|
||||
// const AUTOFILTER_COLUMN_RULE_THISWEEK = 'thisWeek';
|
||||
// const AUTOFILTER_COLUMN_RULE_NEXTWEEK = 'nextWeek';
|
||||
// const AUTOFILTER_COLUMN_RULE_LASTMONTH = 'lastMonth';
|
||||
// const AUTOFILTER_COLUMN_RULE_THISMONTH = 'thisMonth';
|
||||
// const AUTOFILTER_COLUMN_RULE_NEXTMONTH = 'nextMonth';
|
||||
// const AUTOFILTER_COLUMN_RULE_LASTQUARTER = 'lastQuarter';
|
||||
// const AUTOFILTER_COLUMN_RULE_THISQUARTER = 'thisQuarter';
|
||||
// const AUTOFILTER_COLUMN_RULE_NEXTQUARTER = 'nextQuarter';
|
||||
// const AUTOFILTER_COLUMN_RULE_LASTYEAR = 'lastYear';
|
||||
// const AUTOFILTER_COLUMN_RULE_THISYEAR = 'thisYear';
|
||||
// const AUTOFILTER_COLUMN_RULE_NEXTYEAR = 'nextYear';
|
||||
// const AUTOFILTER_COLUMN_RULE_YEARTODATE = 'yearToDate'; // <dynamicFilter val="40909" type="yearToDate" maxVal="41113"/>
|
||||
// const AUTOFILTER_COLUMN_RULE_ALLDATESINMONTH = 'allDatesInMonth'; // <dynamicFilter type="M2"/> for Month/February
|
||||
// const AUTOFILTER_COLUMN_RULE_ALLDATESINQUARTER = 'allDatesInQuarter'; // <dynamicFilter type="Q2"/> for Quarter 2
|
||||
// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
|
||||
// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
|
||||
|
||||
/**
|
||||
* Autofilter Column.
|
||||
*
|
||||
* @var Column
|
||||
* @var ?Column
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
@@ -217,7 +187,7 @@ class Rule
|
||||
/**
|
||||
* Autofilter Rule Value.
|
||||
*
|
||||
* @var string
|
||||
* @var int|int[]|string|string[]
|
||||
*/
|
||||
private $value = '';
|
||||
|
||||
@@ -237,12 +207,17 @@ class Rule
|
||||
|
||||
/**
|
||||
* Create a new Rule.
|
||||
*
|
||||
* @param Column $pParent
|
||||
*/
|
||||
public function __construct(?Column $pParent = null)
|
||||
public function __construct(?Column $parent = null)
|
||||
{
|
||||
$this->parent = $pParent;
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
private function setEvaluatedFalse(): void
|
||||
{
|
||||
if ($this->parent !== null) {
|
||||
$this->parent->setEvaluatedFalse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,17 +233,18 @@ class Rule
|
||||
/**
|
||||
* Set AutoFilter Rule Type.
|
||||
*
|
||||
* @param string $pRuleType see self::AUTOFILTER_RULETYPE_*
|
||||
* @param string $ruleType see self::AUTOFILTER_RULETYPE_*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRuleType($pRuleType)
|
||||
public function setRuleType($ruleType)
|
||||
{
|
||||
if (!in_array($pRuleType, self::$ruleTypes)) {
|
||||
$this->setEvaluatedFalse();
|
||||
if (!in_array($ruleType, self::RULE_TYPES)) {
|
||||
throw new PhpSpreadsheetException('Invalid rule type for column AutoFilter Rule.');
|
||||
}
|
||||
|
||||
$this->ruleType = $pRuleType;
|
||||
$this->ruleType = $ruleType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -276,7 +252,7 @@ class Rule
|
||||
/**
|
||||
* Get AutoFilter Rule Value.
|
||||
*
|
||||
* @return string
|
||||
* @return int|int[]|string|string[]
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
@@ -286,31 +262,32 @@ class Rule
|
||||
/**
|
||||
* Set AutoFilter Rule Value.
|
||||
*
|
||||
* @param string|string[] $pValue
|
||||
* @param int|int[]|string|string[] $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($pValue)
|
||||
public function setValue($value)
|
||||
{
|
||||
if (is_array($pValue)) {
|
||||
$this->setEvaluatedFalse();
|
||||
if (is_array($value)) {
|
||||
$grouping = -1;
|
||||
foreach ($pValue as $key => $value) {
|
||||
foreach ($value as $key => $v) {
|
||||
// Validate array entries
|
||||
if (!in_array($key, self::$dateTimeGroups)) {
|
||||
if (!in_array($key, self::DATE_TIME_GROUPS)) {
|
||||
// Remove any invalid entries from the value array
|
||||
unset($pValue[$key]);
|
||||
unset($value[$key]);
|
||||
} else {
|
||||
// Work out what the dateTime grouping will be
|
||||
$grouping = max($grouping, array_search($key, self::$dateTimeGroups));
|
||||
$grouping = max($grouping, array_search($key, self::DATE_TIME_GROUPS));
|
||||
}
|
||||
}
|
||||
if (count($pValue) == 0) {
|
||||
if (count($value) == 0) {
|
||||
throw new PhpSpreadsheetException('Invalid rule value for column AutoFilter Rule.');
|
||||
}
|
||||
// Set the dateTime grouping that we've anticipated
|
||||
$this->setGrouping(self::$dateTimeGroups[$grouping]);
|
||||
$this->setGrouping(self::DATE_TIME_GROUPS[$grouping]);
|
||||
}
|
||||
$this->value = $pValue;
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -328,22 +305,23 @@ class Rule
|
||||
/**
|
||||
* Set AutoFilter Rule Operator.
|
||||
*
|
||||
* @param string $pOperator see self::AUTOFILTER_COLUMN_RULE_*
|
||||
* @param string $operator see self::AUTOFILTER_COLUMN_RULE_*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOperator($pOperator)
|
||||
public function setOperator($operator)
|
||||
{
|
||||
if (empty($pOperator)) {
|
||||
$pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
|
||||
$this->setEvaluatedFalse();
|
||||
if (empty($operator)) {
|
||||
$operator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
|
||||
}
|
||||
if (
|
||||
(!in_array($pOperator, self::$operators)) &&
|
||||
(!in_array($pOperator, self::$topTenValue))
|
||||
(!in_array($operator, self::OPERATORS)) &&
|
||||
(!in_array($operator, self::TOP_TEN_VALUE))
|
||||
) {
|
||||
throw new PhpSpreadsheetException('Invalid operator for column AutoFilter Rule.');
|
||||
}
|
||||
$this->operator = $pOperator;
|
||||
$this->operator = $operator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -361,21 +339,22 @@ class Rule
|
||||
/**
|
||||
* Set AutoFilter Rule Grouping.
|
||||
*
|
||||
* @param string $pGrouping
|
||||
* @param string $grouping
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setGrouping($pGrouping)
|
||||
public function setGrouping($grouping)
|
||||
{
|
||||
$this->setEvaluatedFalse();
|
||||
if (
|
||||
($pGrouping !== null) &&
|
||||
(!in_array($pGrouping, self::$dateTimeGroups)) &&
|
||||
(!in_array($pGrouping, self::$dynamicTypes)) &&
|
||||
(!in_array($pGrouping, self::$topTenType))
|
||||
($grouping !== null) &&
|
||||
(!in_array($grouping, self::DATE_TIME_GROUPS)) &&
|
||||
(!in_array($grouping, self::DYNAMIC_TYPES)) &&
|
||||
(!in_array($grouping, self::TOP_TEN_TYPE))
|
||||
) {
|
||||
throw new PhpSpreadsheetException('Invalid rule type for column AutoFilter Rule.');
|
||||
throw new PhpSpreadsheetException('Invalid grouping for column AutoFilter Rule.');
|
||||
}
|
||||
$this->grouping = $pGrouping;
|
||||
$this->grouping = $grouping;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -383,21 +362,22 @@ class Rule
|
||||
/**
|
||||
* Set AutoFilter Rule.
|
||||
*
|
||||
* @param string $pOperator see self::AUTOFILTER_COLUMN_RULE_*
|
||||
* @param string|string[] $pValue
|
||||
* @param string $pGrouping
|
||||
* @param string $operator see self::AUTOFILTER_COLUMN_RULE_*
|
||||
* @param int|int[]|string|string[] $value
|
||||
* @param string $grouping
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRule($pOperator, $pValue, $pGrouping = null)
|
||||
public function setRule($operator, $value, $grouping = null)
|
||||
{
|
||||
$this->setOperator($pOperator);
|
||||
$this->setValue($pValue);
|
||||
$this->setEvaluatedFalse();
|
||||
$this->setOperator($operator);
|
||||
$this->setValue($value);
|
||||
// Only set grouping if it's been passed in as a user-supplied argument,
|
||||
// otherwise we're calculating it when we setValue() and don't want to overwrite that
|
||||
// If the user supplies an argumnet for grouping, then on their own head be it
|
||||
if ($pGrouping !== null) {
|
||||
$this->setGrouping($pGrouping);
|
||||
if ($grouping !== null) {
|
||||
$this->setGrouping($grouping);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -406,7 +386,7 @@ class Rule
|
||||
/**
|
||||
* Get this Rule's AutoFilter Column Parent.
|
||||
*
|
||||
* @return Column
|
||||
* @return ?Column
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
@@ -416,13 +396,12 @@ class Rule
|
||||
/**
|
||||
* Set this Rule's AutoFilter Column Parent.
|
||||
*
|
||||
* @param Column $pParent
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(?Column $pParent = null)
|
||||
public function setParent(?Column $parent = null)
|
||||
{
|
||||
$this->parent = $pParent;
|
||||
$this->setEvaluatedFalse();
|
||||
$this->parent = $parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -435,11 +414,9 @@ class Rule
|
||||
$vars = get_object_vars($this);
|
||||
foreach ($vars as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
if ($key == 'parent') {
|
||||
if ($key == 'parent') { // this is only object
|
||||
// Detach from autofilter column parent
|
||||
$this->$key = null;
|
||||
} else {
|
||||
$this->$key = clone $value;
|
||||
}
|
||||
} else {
|
||||
$this->$key = $value;
|
||||
|
@@ -8,6 +8,22 @@ use PhpOffice\PhpSpreadsheet\IComparable;
|
||||
|
||||
class BaseDrawing implements IComparable
|
||||
{
|
||||
const EDIT_AS_ABSOLUTE = 'absolute';
|
||||
const EDIT_AS_ONECELL = 'oneCell';
|
||||
const EDIT_AS_TWOCELL = 'twoCell';
|
||||
private const VALID_EDIT_AS = [
|
||||
self::EDIT_AS_ABSOLUTE,
|
||||
self::EDIT_AS_ONECELL,
|
||||
self::EDIT_AS_TWOCELL,
|
||||
];
|
||||
|
||||
/**
|
||||
* The editAs attribute, used only with two cell anchor.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $editAs = '';
|
||||
|
||||
/**
|
||||
* Image counter.
|
||||
*
|
||||
@@ -27,19 +43,19 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
protected $name = '';
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
protected $description = '';
|
||||
|
||||
/**
|
||||
* Worksheet.
|
||||
*
|
||||
* @var Worksheet
|
||||
* @var null|Worksheet
|
||||
*/
|
||||
protected $worksheet;
|
||||
|
||||
@@ -48,49 +64,84 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $coordinates;
|
||||
protected $coordinates = 'A1';
|
||||
|
||||
/**
|
||||
* Offset X.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetX;
|
||||
protected $offsetX = 0;
|
||||
|
||||
/**
|
||||
* Offset Y.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetY;
|
||||
protected $offsetY = 0;
|
||||
|
||||
/**
|
||||
* Coordinates2.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $coordinates2 = '';
|
||||
|
||||
/**
|
||||
* Offset X2.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetX2 = 0;
|
||||
|
||||
/**
|
||||
* Offset Y2.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $offsetY2 = 0;
|
||||
|
||||
/**
|
||||
* Width.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $width;
|
||||
protected $width = 0;
|
||||
|
||||
/**
|
||||
* Height.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $height;
|
||||
protected $height = 0;
|
||||
|
||||
/**
|
||||
* Pixel width of image. See $width for the size the Drawing will be in the sheet.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $imageWidth = 0;
|
||||
|
||||
/**
|
||||
* Pixel width of image. See $height for the size the Drawing will be in the sheet.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $imageHeight = 0;
|
||||
|
||||
/**
|
||||
* Proportional resize.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $resizeProportional;
|
||||
protected $resizeProportional = true;
|
||||
|
||||
/**
|
||||
* Rotation.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $rotation;
|
||||
protected $rotation = 0;
|
||||
|
||||
/**
|
||||
* Shadow.
|
||||
@@ -106,93 +157,56 @@ class BaseDrawing implements IComparable
|
||||
*/
|
||||
private $hyperlink;
|
||||
|
||||
/**
|
||||
* Image type.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type = IMAGETYPE_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Create a new BaseDrawing.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Initialise values
|
||||
$this->name = '';
|
||||
$this->description = '';
|
||||
$this->worksheet = null;
|
||||
$this->coordinates = 'A1';
|
||||
$this->offsetX = 0;
|
||||
$this->offsetY = 0;
|
||||
$this->width = 0;
|
||||
$this->height = 0;
|
||||
$this->resizeProportional = true;
|
||||
$this->rotation = 0;
|
||||
$this->shadow = new Drawing\Shadow();
|
||||
$this->setShadow();
|
||||
|
||||
// Set image index
|
||||
++self::$imageCounter;
|
||||
$this->imageIndex = self::$imageCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getImageIndex()
|
||||
public function getImageIndex(): int
|
||||
{
|
||||
return $this->imageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Name.
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($pValue)
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $pValue;
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Description.
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
public function setDescription(string $description): self
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Worksheet.
|
||||
*
|
||||
* @return Worksheet
|
||||
*/
|
||||
public function getWorksheet()
|
||||
public function getWorksheet(): ?Worksheet
|
||||
{
|
||||
return $this->worksheet;
|
||||
}
|
||||
@@ -200,26 +214,25 @@ class BaseDrawing implements IComparable
|
||||
/**
|
||||
* Set Worksheet.
|
||||
*
|
||||
* @param Worksheet $pValue
|
||||
* @param bool $pOverrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
|
||||
*
|
||||
* @return $this
|
||||
* @param bool $overrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
|
||||
*/
|
||||
public function setWorksheet(?Worksheet $pValue = null, $pOverrideOld = false)
|
||||
public function setWorksheet(?Worksheet $worksheet = null, bool $overrideOld = false): self
|
||||
{
|
||||
if ($this->worksheet === null) {
|
||||
// Add drawing to \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
|
||||
$this->worksheet = $pValue;
|
||||
$this->worksheet->getCell($this->coordinates);
|
||||
$this->worksheet->getDrawingCollection()->append($this);
|
||||
if ($worksheet !== null) {
|
||||
$this->worksheet = $worksheet;
|
||||
$this->worksheet->getCell($this->coordinates);
|
||||
$this->worksheet->getDrawingCollection()->append($this);
|
||||
}
|
||||
} else {
|
||||
if ($pOverrideOld) {
|
||||
if ($overrideOld) {
|
||||
// Remove drawing from old \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
|
||||
$iterator = $this->worksheet->getDrawingCollection()->getIterator();
|
||||
|
||||
while ($iterator->valid()) {
|
||||
if ($iterator->current()->getHashCode() === $this->getHashCode()) {
|
||||
$this->worksheet->getDrawingCollection()->offsetUnset($iterator->key());
|
||||
$this->worksheet->getDrawingCollection()->offsetUnset(/** @scrutinizer ignore-type */ $iterator->key());
|
||||
$this->worksheet = null;
|
||||
|
||||
break;
|
||||
@@ -227,7 +240,7 @@ class BaseDrawing implements IComparable
|
||||
}
|
||||
|
||||
// Set new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
|
||||
$this->setWorksheet($pValue);
|
||||
$this->setWorksheet($worksheet);
|
||||
} else {
|
||||
throw new PhpSpreadsheetException('A Worksheet has already been assigned. Drawings can only exist on one \\PhpOffice\\PhpSpreadsheet\\Worksheet.');
|
||||
}
|
||||
@@ -236,136 +249,112 @@ class BaseDrawing implements IComparable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Coordinates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCoordinates()
|
||||
public function getCoordinates(): string
|
||||
{
|
||||
return $this->coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Coordinates.
|
||||
*
|
||||
* @param string $pValue eg: 'A1'
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCoordinates($pValue)
|
||||
public function setCoordinates(string $coordinates): self
|
||||
{
|
||||
$this->coordinates = $pValue;
|
||||
$this->coordinates = $coordinates;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetX.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetX()
|
||||
public function getOffsetX(): int
|
||||
{
|
||||
return $this->offsetX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetX.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetX($pValue)
|
||||
public function setOffsetX(int $offsetX): self
|
||||
{
|
||||
$this->offsetX = $pValue;
|
||||
$this->offsetX = $offsetX;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OffsetY.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOffsetY()
|
||||
public function getOffsetY(): int
|
||||
{
|
||||
return $this->offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OffsetY.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetY($pValue)
|
||||
public function setOffsetY(int $offsetY): self
|
||||
{
|
||||
$this->offsetY = $pValue;
|
||||
$this->offsetY = $offsetY;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Width.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth()
|
||||
public function getCoordinates2(): string
|
||||
{
|
||||
return $this->coordinates2;
|
||||
}
|
||||
|
||||
public function setCoordinates2(string $coordinates2): self
|
||||
{
|
||||
$this->coordinates2 = $coordinates2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOffsetX2(): int
|
||||
{
|
||||
return $this->offsetX2;
|
||||
}
|
||||
|
||||
public function setOffsetX2(int $offsetX2): self
|
||||
{
|
||||
$this->offsetX2 = $offsetX2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOffsetY2(): int
|
||||
{
|
||||
return $this->offsetY2;
|
||||
}
|
||||
|
||||
public function setOffsetY2(int $offsetY2): self
|
||||
{
|
||||
$this->offsetY2 = $offsetY2;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getWidth(): int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Width.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($pValue)
|
||||
public function setWidth(int $width): self
|
||||
{
|
||||
// Resize proportional?
|
||||
if ($this->resizeProportional && $pValue != 0) {
|
||||
if ($this->resizeProportional && $width != 0) {
|
||||
$ratio = $this->height / ($this->width != 0 ? $this->width : 1);
|
||||
$this->height = round($ratio * $pValue);
|
||||
$this->height = (int) round($ratio * $width);
|
||||
}
|
||||
|
||||
// Set width
|
||||
$this->width = $pValue;
|
||||
$this->width = $width;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Height.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight()
|
||||
public function getHeight(): int
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Height.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($pValue)
|
||||
public function setHeight(int $height): self
|
||||
{
|
||||
// Resize proportional?
|
||||
if ($this->resizeProportional && $pValue != 0) {
|
||||
if ($this->resizeProportional && $height != 0) {
|
||||
$ratio = $this->width / ($this->height != 0 ? $this->height : 1);
|
||||
$this->width = round($ratio * $pValue);
|
||||
$this->width = (int) round($ratio * $height);
|
||||
}
|
||||
|
||||
// Set height
|
||||
$this->height = $pValue;
|
||||
$this->height = $height;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -380,22 +369,17 @@ class BaseDrawing implements IComparable
|
||||
* </code>
|
||||
*
|
||||
* @author Vincent@luo MSN:kele_100@hotmail.com
|
||||
*
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidthAndHeight($width, $height)
|
||||
public function setWidthAndHeight(int $width, int $height): self
|
||||
{
|
||||
$xratio = $width / ($this->width != 0 ? $this->width : 1);
|
||||
$yratio = $height / ($this->height != 0 ? $this->height : 1);
|
||||
if ($this->resizeProportional && !($width == 0 || $height == 0)) {
|
||||
if (($xratio * $this->height) < $height) {
|
||||
$this->height = ceil($xratio * $this->height);
|
||||
$this->height = (int) ceil($xratio * $this->height);
|
||||
$this->width = $width;
|
||||
} else {
|
||||
$this->width = ceil($yratio * $this->width);
|
||||
$this->width = (int) ceil($yratio * $this->width);
|
||||
$this->height = $height;
|
||||
}
|
||||
} else {
|
||||
@@ -406,74 +390,38 @@ class BaseDrawing implements IComparable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ResizeProportional.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getResizeProportional()
|
||||
public function getResizeProportional(): bool
|
||||
{
|
||||
return $this->resizeProportional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ResizeProportional.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setResizeProportional($pValue)
|
||||
public function setResizeProportional(bool $resizeProportional): self
|
||||
{
|
||||
$this->resizeProportional = $pValue;
|
||||
$this->resizeProportional = $resizeProportional;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Rotation.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRotation()
|
||||
public function getRotation(): int
|
||||
{
|
||||
return $this->rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Rotation.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRotation($pValue)
|
||||
public function setRotation(int $rotation): self
|
||||
{
|
||||
$this->rotation = $pValue;
|
||||
$this->rotation = $rotation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Shadow.
|
||||
*
|
||||
* @return Drawing\Shadow
|
||||
*/
|
||||
public function getShadow()
|
||||
public function getShadow(): Drawing\Shadow
|
||||
{
|
||||
return $this->shadow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Shadow.
|
||||
*
|
||||
* @param Drawing\Shadow $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setShadow(?Drawing\Shadow $pValue = null)
|
||||
public function setShadow(?Drawing\Shadow $shadow = null): self
|
||||
{
|
||||
$this->shadow = $pValue;
|
||||
$this->shadow = $shadow ?? new Drawing\Shadow();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -488,10 +436,13 @@ class BaseDrawing implements IComparable
|
||||
return md5(
|
||||
$this->name .
|
||||
$this->description .
|
||||
$this->worksheet->getHashCode() .
|
||||
(($this->worksheet === null) ? '' : $this->worksheet->getHashCode()) .
|
||||
$this->coordinates .
|
||||
$this->offsetX .
|
||||
$this->offsetY .
|
||||
$this->coordinates2 .
|
||||
$this->offsetX2 .
|
||||
$this->offsetY2 .
|
||||
$this->width .
|
||||
$this->height .
|
||||
$this->rotation .
|
||||
@@ -517,16 +468,68 @@ class BaseDrawing implements IComparable
|
||||
}
|
||||
}
|
||||
|
||||
public function setHyperlink(?Hyperlink $pHyperlink = null): void
|
||||
public function setHyperlink(?Hyperlink $hyperlink = null): void
|
||||
{
|
||||
$this->hyperlink = $pHyperlink;
|
||||
$this->hyperlink = $hyperlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|Hyperlink
|
||||
*/
|
||||
public function getHyperlink()
|
||||
public function getHyperlink(): ?Hyperlink
|
||||
{
|
||||
return $this->hyperlink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Fact Sizes and Type of Image.
|
||||
*/
|
||||
protected function setSizesAndType(string $path): void
|
||||
{
|
||||
if ($this->imageWidth === 0 && $this->imageHeight === 0 && $this->type === IMAGETYPE_UNKNOWN) {
|
||||
$imageData = getimagesize($path);
|
||||
|
||||
if (!empty($imageData)) {
|
||||
$this->imageWidth = $imageData[0];
|
||||
$this->imageHeight = $imageData[1];
|
||||
$this->type = $imageData[2];
|
||||
}
|
||||
}
|
||||
if ($this->width === 0 && $this->height === 0) {
|
||||
$this->width = $this->imageWidth;
|
||||
$this->height = $this->imageHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Image Type.
|
||||
*/
|
||||
public function getType(): int
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getImageWidth(): int
|
||||
{
|
||||
return $this->imageWidth;
|
||||
}
|
||||
|
||||
public function getImageHeight(): int
|
||||
{
|
||||
return $this->imageHeight;
|
||||
}
|
||||
|
||||
public function getEditAs(): string
|
||||
{
|
||||
return $this->editAs;
|
||||
}
|
||||
|
||||
public function setEditAs(string $editAs): self
|
||||
{
|
||||
$this->editAs = $editAs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function validEditAs(): bool
|
||||
{
|
||||
return in_array($this->editAs, self::VALID_EDIT_AS, true);
|
||||
}
|
||||
}
|
||||
|
@@ -2,10 +2,21 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use Iterator;
|
||||
use Iterator as NativeIterator;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Collection\Cells;
|
||||
|
||||
abstract class CellIterator implements Iterator
|
||||
/**
|
||||
* @template TKey
|
||||
*
|
||||
* @implements NativeIterator<TKey, Cell>
|
||||
*/
|
||||
abstract class CellIterator implements NativeIterator
|
||||
{
|
||||
public const TREAT_NULL_VALUE_AS_EMPTY_CELL = 1;
|
||||
|
||||
public const TREAT_EMPTY_STRING_AS_EMPTY_CELL = 2;
|
||||
|
||||
/**
|
||||
* Worksheet to iterate.
|
||||
*
|
||||
@@ -13,6 +24,13 @@ abstract class CellIterator implements Iterator
|
||||
*/
|
||||
protected $worksheet;
|
||||
|
||||
/**
|
||||
* Cell Collection to iterate.
|
||||
*
|
||||
* @var Cells
|
||||
*/
|
||||
protected $cellCollection;
|
||||
|
||||
/**
|
||||
* Iterate only existing cells.
|
||||
*
|
||||
@@ -25,15 +43,14 @@ abstract class CellIterator implements Iterator
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->worksheet = null;
|
||||
// @phpstan-ignore-next-line
|
||||
$this->worksheet = $this->cellCollection = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get loop only existing cells.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIterateOnlyExistingCells()
|
||||
public function getIterateOnlyExistingCells(): bool
|
||||
{
|
||||
return $this->onlyExistingCells;
|
||||
}
|
||||
@@ -45,10 +62,8 @@ abstract class CellIterator implements Iterator
|
||||
|
||||
/**
|
||||
* Set the iterator to loop only existing cells.
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setIterateOnlyExistingCells($value): void
|
||||
public function setIterateOnlyExistingCells(bool $value): void
|
||||
{
|
||||
$this->onlyExistingCells = (bool) $value;
|
||||
|
||||
|
@@ -9,7 +9,7 @@ class Column
|
||||
*
|
||||
* @var Worksheet
|
||||
*/
|
||||
private $parent;
|
||||
private $worksheet;
|
||||
|
||||
/**
|
||||
* Column index.
|
||||
@@ -21,13 +21,12 @@ class Column
|
||||
/**
|
||||
* Create a new column.
|
||||
*
|
||||
* @param Worksheet $parent
|
||||
* @param string $columnIndex
|
||||
*/
|
||||
public function __construct(?Worksheet $parent = null, $columnIndex = 'A')
|
||||
public function __construct(Worksheet $worksheet, $columnIndex = 'A')
|
||||
{
|
||||
// Set parent and column index
|
||||
$this->parent = $parent;
|
||||
$this->worksheet = $worksheet;
|
||||
$this->columnIndex = $columnIndex;
|
||||
}
|
||||
|
||||
@@ -36,15 +35,14 @@ class Column
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->parent = null;
|
||||
// @phpstan-ignore-next-line
|
||||
$this->worksheet = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column index as string eg: 'A'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnIndex()
|
||||
public function getColumnIndex(): string
|
||||
{
|
||||
return $this->columnIndex;
|
||||
}
|
||||
@@ -59,6 +57,54 @@ class Column
|
||||
*/
|
||||
public function getCellIterator($startRow = 1, $endRow = null)
|
||||
{
|
||||
return new ColumnCellIterator($this->parent, $this->columnIndex, $startRow, $endRow);
|
||||
return new ColumnCellIterator($this->worksheet, $this->columnIndex, $startRow, $endRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean true if the column contains no cells. By default, this means that no cell records exist in the
|
||||
* collection for this column. false will be returned otherwise.
|
||||
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||
* cells, then the column will be considered empty.
|
||||
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||
* string value cells, then the column will be considered empty.
|
||||
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||
* If the only cells in the collection are null value or empty string value cells, then the column
|
||||
* will be considered empty.
|
||||
*
|
||||
* @param int $definitionOfEmptyFlags
|
||||
* Possible Flag Values are:
|
||||
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||
*/
|
||||
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||
{
|
||||
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||
|
||||
$cellIterator = $this->getCellIterator();
|
||||
$cellIterator->setIterateOnlyExistingCells(true);
|
||||
foreach ($cellIterator as $cell) {
|
||||
/** @scrutinizer ignore-call */
|
||||
$value = $cell->getValue();
|
||||
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||
continue;
|
||||
}
|
||||
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bound worksheet.
|
||||
*/
|
||||
public function getWorksheet(): Worksheet
|
||||
{
|
||||
return $this->worksheet;
|
||||
}
|
||||
}
|
||||
|
@@ -2,9 +2,13 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
/**
|
||||
* @extends CellIterator<int>
|
||||
*/
|
||||
class ColumnCellIterator extends CellIterator
|
||||
{
|
||||
/**
|
||||
@@ -17,7 +21,7 @@ class ColumnCellIterator extends CellIterator
|
||||
/**
|
||||
* Column index.
|
||||
*
|
||||
* @var string
|
||||
* @var int
|
||||
*/
|
||||
private $columnIndex;
|
||||
|
||||
@@ -38,15 +42,16 @@ class ColumnCellIterator extends CellIterator
|
||||
/**
|
||||
* Create a new row iterator.
|
||||
*
|
||||
* @param Worksheet $subject The worksheet to iterate over
|
||||
* @param Worksheet $worksheet The worksheet to iterate over
|
||||
* @param string $columnIndex The column that we want to iterate
|
||||
* @param int $startRow The row number at which to start iterating
|
||||
* @param int $endRow Optionally, the row number at which to stop iterating
|
||||
*/
|
||||
public function __construct(?Worksheet $subject = null, $columnIndex = 'A', $startRow = 1, $endRow = null)
|
||||
public function __construct(Worksheet $worksheet, $columnIndex = 'A', $startRow = 1, $endRow = null)
|
||||
{
|
||||
// Set subject
|
||||
$this->worksheet = $subject;
|
||||
$this->worksheet = $worksheet;
|
||||
$this->cellCollection = $worksheet->getCellCollection();
|
||||
$this->columnIndex = Coordinate::columnIndexFromString($columnIndex);
|
||||
$this->resetEnd($endRow);
|
||||
$this->resetStart($startRow);
|
||||
@@ -59,7 +64,7 @@ class ColumnCellIterator extends CellIterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startRow = 1)
|
||||
public function resetStart(int $startRow = 1)
|
||||
{
|
||||
$this->startRow = $startRow;
|
||||
$this->adjustForExistingOnlyRange();
|
||||
@@ -77,7 +82,7 @@ class ColumnCellIterator extends CellIterator
|
||||
*/
|
||||
public function resetEnd($endRow = null)
|
||||
{
|
||||
$this->endRow = ($endRow) ? $endRow : $this->worksheet->getHighestRow();
|
||||
$this->endRow = $endRow ?: $this->worksheet->getHighestRow();
|
||||
$this->adjustForExistingOnlyRange();
|
||||
|
||||
return $this;
|
||||
@@ -90,9 +95,12 @@ class ColumnCellIterator extends CellIterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($row = 1)
|
||||
public function seek(int $row = 1)
|
||||
{
|
||||
if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $row))) {
|
||||
if (
|
||||
$this->onlyExistingCells &&
|
||||
(!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->columnIndex) . $row))
|
||||
) {
|
||||
throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
|
||||
}
|
||||
if (($row < $this->startRow) || ($row > $this->endRow)) {
|
||||
@@ -113,20 +121,20 @@ class ColumnCellIterator extends CellIterator
|
||||
|
||||
/**
|
||||
* Return the current cell in this worksheet column.
|
||||
*
|
||||
* @return \PhpOffice\PhpSpreadsheet\Cell\Cell
|
||||
*/
|
||||
public function current()
|
||||
public function current(): ?Cell
|
||||
{
|
||||
return $this->worksheet->getCellByColumnAndRow($this->columnIndex, $this->currentRow);
|
||||
$cellAddress = Coordinate::stringFromColumnIndex($this->columnIndex) . $this->currentRow;
|
||||
|
||||
return $this->cellCollection->has($cellAddress)
|
||||
? $this->cellCollection->get($cellAddress)
|
||||
: $this->worksheet->createNewCell($cellAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current iterator key.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function key()
|
||||
public function key(): int
|
||||
{
|
||||
return $this->currentRow;
|
||||
}
|
||||
@@ -136,12 +144,13 @@ class ColumnCellIterator extends CellIterator
|
||||
*/
|
||||
public function next(): void
|
||||
{
|
||||
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
|
||||
do {
|
||||
++$this->currentRow;
|
||||
} while (
|
||||
($this->onlyExistingCells) &&
|
||||
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->currentRow)) &&
|
||||
($this->currentRow <= $this->endRow)
|
||||
($this->currentRow <= $this->endRow) &&
|
||||
(!$this->cellCollection->has($columnAddress . $this->currentRow))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -150,21 +159,20 @@ class ColumnCellIterator extends CellIterator
|
||||
*/
|
||||
public function prev(): void
|
||||
{
|
||||
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
|
||||
do {
|
||||
--$this->currentRow;
|
||||
} while (
|
||||
($this->onlyExistingCells) &&
|
||||
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->currentRow)) &&
|
||||
($this->currentRow >= $this->startRow)
|
||||
($this->currentRow >= $this->startRow) &&
|
||||
(!$this->cellCollection->has($columnAddress . $this->currentRow))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if more rows exist in the worksheet range of rows that we're iterating.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->currentRow <= $this->endRow && $this->currentRow >= $this->startRow;
|
||||
}
|
||||
@@ -175,14 +183,15 @@ class ColumnCellIterator extends CellIterator
|
||||
protected function adjustForExistingOnlyRange(): void
|
||||
{
|
||||
if ($this->onlyExistingCells) {
|
||||
$columnAddress = Coordinate::stringFromColumnIndex($this->columnIndex);
|
||||
while (
|
||||
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->startRow)) &&
|
||||
(!$this->cellCollection->has($columnAddress . $this->startRow)) &&
|
||||
($this->startRow <= $this->endRow)
|
||||
) {
|
||||
++$this->startRow;
|
||||
}
|
||||
while (
|
||||
(!$this->worksheet->cellExistsByColumnAndRow($this->columnIndex, $this->endRow)) &&
|
||||
(!$this->cellCollection->has($columnAddress . $this->endRow)) &&
|
||||
($this->endRow >= $this->startRow)
|
||||
) {
|
||||
--$this->endRow;
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Helper\Dimension as CssDimension;
|
||||
|
||||
class ColumnDimension extends Dimension
|
||||
{
|
||||
/**
|
||||
@@ -30,12 +33,12 @@ class ColumnDimension extends Dimension
|
||||
/**
|
||||
* Create a new ColumnDimension.
|
||||
*
|
||||
* @param string $pIndex Character column index
|
||||
* @param string $index Character column index
|
||||
*/
|
||||
public function __construct($pIndex = 'A')
|
||||
public function __construct($index = 'A')
|
||||
{
|
||||
// Initialise values
|
||||
$this->columnIndex = $pIndex;
|
||||
$this->columnIndex = $index;
|
||||
|
||||
// set dimension as unformatted by default
|
||||
parent::__construct(0);
|
||||
@@ -43,24 +46,36 @@ class ColumnDimension extends Dimension
|
||||
|
||||
/**
|
||||
* Get column index as string eg: 'A'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getColumnIndex()
|
||||
public function getColumnIndex(): string
|
||||
{
|
||||
return $this->columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column index as string eg: 'A'.
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnIndex($pValue)
|
||||
public function setColumnIndex(string $index): self
|
||||
{
|
||||
$this->columnIndex = $pValue;
|
||||
$this->columnIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column index as numeric.
|
||||
*/
|
||||
public function getColumnNumeric(): int
|
||||
{
|
||||
return Coordinate::columnIndexFromString($this->columnIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column index as numeric.
|
||||
*/
|
||||
public function setColumnNumeric(int $index): self
|
||||
{
|
||||
$this->columnIndex = Coordinate::stringFromColumnIndex($index);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -68,33 +83,42 @@ class ColumnDimension extends Dimension
|
||||
/**
|
||||
* Get Width.
|
||||
*
|
||||
* @return float
|
||||
* Each unit of column width is equal to the width of one character in the default font size. A value of -1
|
||||
* tells Excel to display this column in its default width.
|
||||
* By default, this will be the return value; but this method also accepts an optional unit of measure argument
|
||||
* and will convert the returned value to the specified UoM..
|
||||
*/
|
||||
public function getWidth()
|
||||
public function getWidth(?string $unitOfMeasure = null): float
|
||||
{
|
||||
return $this->width;
|
||||
return ($unitOfMeasure === null || $this->width < 0)
|
||||
? $this->width
|
||||
: (new CssDimension((string) $this->width))->toUnit($unitOfMeasure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Width.
|
||||
*
|
||||
* @param float $pValue
|
||||
* Each unit of column width is equal to the width of one character in the default font size. A value of -1
|
||||
* tells Excel to display this column in its default width.
|
||||
* By default, this will be the unit of measure for the passed value; but this method also accepts an
|
||||
* optional unit of measure argument, and will convert the value from the specified UoM using an
|
||||
* approximation method.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($pValue)
|
||||
public function setWidth(float $width, ?string $unitOfMeasure = null)
|
||||
{
|
||||
$this->width = $pValue;
|
||||
$this->width = ($unitOfMeasure === null || $width < 0)
|
||||
? $width
|
||||
: (new CssDimension("{$width}{$unitOfMeasure}"))->width();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Auto Size.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getAutoSize()
|
||||
public function getAutoSize(): bool
|
||||
{
|
||||
return $this->autoSize;
|
||||
}
|
||||
@@ -102,13 +126,11 @@ class ColumnDimension extends Dimension
|
||||
/**
|
||||
* Set Auto Size.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoSize($pValue)
|
||||
public function setAutoSize(bool $autosizeEnabled)
|
||||
{
|
||||
$this->autoSize = $pValue;
|
||||
$this->autoSize = $autosizeEnabled;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -2,12 +2,15 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use Iterator;
|
||||
use Iterator as NativeIterator;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
class ColumnIterator implements Iterator
|
||||
/**
|
||||
* @implements NativeIterator<string, Column>
|
||||
*/
|
||||
class ColumnIterator implements NativeIterator
|
||||
{
|
||||
/**
|
||||
* Worksheet to iterate.
|
||||
@@ -57,6 +60,7 @@ class ColumnIterator implements Iterator
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->worksheet = null;
|
||||
}
|
||||
|
||||
@@ -67,11 +71,13 @@ class ColumnIterator implements Iterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startColumn = 'A')
|
||||
public function resetStart(string $startColumn = 'A')
|
||||
{
|
||||
$startColumnIndex = Coordinate::columnIndexFromString($startColumn);
|
||||
if ($startColumnIndex > Coordinate::columnIndexFromString($this->worksheet->getHighestColumn())) {
|
||||
throw new Exception("Start column ({$startColumn}) is beyond highest column ({$this->worksheet->getHighestColumn()})");
|
||||
throw new Exception(
|
||||
"Start column ({$startColumn}) is beyond highest column ({$this->worksheet->getHighestColumn()})"
|
||||
);
|
||||
}
|
||||
|
||||
$this->startColumnIndex = $startColumnIndex;
|
||||
@@ -92,7 +98,7 @@ class ColumnIterator implements Iterator
|
||||
*/
|
||||
public function resetEnd($endColumn = null)
|
||||
{
|
||||
$endColumn = $endColumn ? $endColumn : $this->worksheet->getHighestColumn();
|
||||
$endColumn = $endColumn ?: $this->worksheet->getHighestColumn();
|
||||
$this->endColumnIndex = Coordinate::columnIndexFromString($endColumn);
|
||||
|
||||
return $this;
|
||||
@@ -105,11 +111,13 @@ class ColumnIterator implements Iterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($column = 'A')
|
||||
public function seek(string $column = 'A')
|
||||
{
|
||||
$column = Coordinate::columnIndexFromString($column);
|
||||
if (($column < $this->startColumnIndex) || ($column > $this->endColumnIndex)) {
|
||||
throw new PhpSpreadsheetException("Column $column is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
|
||||
throw new PhpSpreadsheetException(
|
||||
"Column $column is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})"
|
||||
);
|
||||
}
|
||||
$this->currentColumnIndex = $column;
|
||||
|
||||
@@ -126,20 +134,16 @@ class ColumnIterator implements Iterator
|
||||
|
||||
/**
|
||||
* Return the current column in this worksheet.
|
||||
*
|
||||
* @return Column
|
||||
*/
|
||||
public function current()
|
||||
public function current(): Column
|
||||
{
|
||||
return new Column($this->worksheet, Coordinate::stringFromColumnIndex($this->currentColumnIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current iterator key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function key()
|
||||
public function key(): string
|
||||
{
|
||||
return Coordinate::stringFromColumnIndex($this->currentColumnIndex);
|
||||
}
|
||||
@@ -162,10 +166,8 @@ class ColumnIterator implements Iterator
|
||||
|
||||
/**
|
||||
* Indicate if more columns exist in the worksheet range of columns that we're iterating.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->currentColumnIndex <= $this->endColumnIndex && $this->currentColumnIndex >= $this->startColumnIndex;
|
||||
}
|
||||
|
@@ -47,10 +47,8 @@ abstract class Dimension
|
||||
|
||||
/**
|
||||
* Get Visible.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getVisible()
|
||||
public function getVisible(): bool
|
||||
{
|
||||
return $this->visible;
|
||||
}
|
||||
@@ -58,23 +56,19 @@ abstract class Dimension
|
||||
/**
|
||||
* Set Visible.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible($pValue)
|
||||
public function setVisible(bool $visible)
|
||||
{
|
||||
$this->visible = (bool) $pValue;
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Outline Level.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOutlineLevel()
|
||||
public function getOutlineLevel(): int
|
||||
{
|
||||
return $this->outlineLevel;
|
||||
}
|
||||
@@ -83,27 +77,23 @@ abstract class Dimension
|
||||
* Set Outline Level.
|
||||
* Value must be between 0 and 7.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOutlineLevel($pValue)
|
||||
public function setOutlineLevel(int $level)
|
||||
{
|
||||
if ($pValue < 0 || $pValue > 7) {
|
||||
if ($level < 0 || $level > 7) {
|
||||
throw new PhpSpreadsheetException('Outline level must range between 0 and 7.');
|
||||
}
|
||||
|
||||
$this->outlineLevel = $pValue;
|
||||
$this->outlineLevel = $level;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Collapsed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getCollapsed()
|
||||
public function getCollapsed(): bool
|
||||
{
|
||||
return $this->collapsed;
|
||||
}
|
||||
@@ -111,13 +101,11 @@ abstract class Dimension
|
||||
/**
|
||||
* Set Collapsed.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setCollapsed($pValue)
|
||||
public function setCollapsed(bool $collapsed)
|
||||
{
|
||||
$this->collapsed = (bool) $pValue;
|
||||
$this->collapsed = $collapsed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -127,7 +115,7 @@ abstract class Dimension
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getXfIndex()
|
||||
public function getXfIndex(): ?int
|
||||
{
|
||||
return $this->xfIndex;
|
||||
}
|
||||
@@ -135,29 +123,12 @@ abstract class Dimension
|
||||
/**
|
||||
* Set index to cellXf.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setXfIndex($pValue)
|
||||
public function setXfIndex(int $XfIndex)
|
||||
{
|
||||
$this->xfIndex = $pValue;
|
||||
$this->xfIndex = $XfIndex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
foreach ($vars as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
$this->$key = clone $value;
|
||||
} else {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,9 +3,17 @@
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use ZipArchive;
|
||||
|
||||
class Drawing extends BaseDrawing
|
||||
{
|
||||
const IMAGE_TYPES_CONVERTION_MAP = [
|
||||
IMAGETYPE_GIF => IMAGETYPE_PNG,
|
||||
IMAGETYPE_JPEG => IMAGETYPE_JPEG,
|
||||
IMAGETYPE_PNG => IMAGETYPE_PNG,
|
||||
IMAGETYPE_BMP => IMAGETYPE_PNG,
|
||||
];
|
||||
|
||||
/**
|
||||
* Path.
|
||||
*
|
||||
@@ -13,6 +21,13 @@ class Drawing extends BaseDrawing
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* Whether or not we are dealing with a URL.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isUrl;
|
||||
|
||||
/**
|
||||
* Create a new Drawing.
|
||||
*/
|
||||
@@ -20,6 +35,7 @@ class Drawing extends BaseDrawing
|
||||
{
|
||||
// Initialise values
|
||||
$this->path = '';
|
||||
$this->isUrl = false;
|
||||
|
||||
// Initialize parent
|
||||
parent::__construct();
|
||||
@@ -37,15 +53,10 @@ class Drawing extends BaseDrawing
|
||||
|
||||
/**
|
||||
* Get indexed filename (using image index).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIndexedFilename()
|
||||
public function getIndexedFilename(): string
|
||||
{
|
||||
$fileName = $this->getFilename();
|
||||
$fileName = str_replace(' ', '_', $fileName);
|
||||
|
||||
return str_replace('.' . $this->getExtension(), '', $fileName) . $this->getImageIndex() . '.' . $this->getExtension();
|
||||
return md5($this->path) . '.' . $this->getExtension();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,6 +71,20 @@ class Drawing extends BaseDrawing
|
||||
return $exploded[count($exploded) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full filepath to store drawing in zip archive.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMediaFilename()
|
||||
{
|
||||
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
return sprintf('image%d%s', $this->getImageIndex(), $this->getImageFileExtensionForSave());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Path.
|
||||
*
|
||||
@@ -73,31 +98,68 @@ class Drawing extends BaseDrawing
|
||||
/**
|
||||
* Set Path.
|
||||
*
|
||||
* @param string $pValue File path
|
||||
* @param bool $pVerifyFile Verify file
|
||||
* @param string $path File path
|
||||
* @param bool $verifyFile Verify file
|
||||
* @param ZipArchive $zip Zip archive instance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPath($pValue, $pVerifyFile = true)
|
||||
public function setPath($path, $verifyFile = true, $zip = null)
|
||||
{
|
||||
if ($pVerifyFile) {
|
||||
if (file_exists($pValue)) {
|
||||
$this->path = $pValue;
|
||||
|
||||
if ($this->width == 0 && $this->height == 0) {
|
||||
// Get width/height
|
||||
[$this->width, $this->height] = getimagesize($pValue);
|
||||
if ($verifyFile && preg_match('~^data:image/[a-z]+;base64,~', $path) !== 1) {
|
||||
// Check if a URL has been passed. https://stackoverflow.com/a/2058596/1252979
|
||||
if (filter_var($path, FILTER_VALIDATE_URL)) {
|
||||
$this->path = $path;
|
||||
// Implicit that it is a URL, rather store info than running check above on value in other places.
|
||||
$this->isUrl = true;
|
||||
$imageContents = file_get_contents($path);
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'Drawing');
|
||||
if ($filePath) {
|
||||
file_put_contents($filePath, $imageContents);
|
||||
if (file_exists($filePath)) {
|
||||
$this->setSizesAndType($filePath);
|
||||
unlink($filePath);
|
||||
}
|
||||
}
|
||||
} elseif (file_exists($path)) {
|
||||
$this->path = $path;
|
||||
$this->setSizesAndType($path);
|
||||
} elseif ($zip instanceof ZipArchive) {
|
||||
$zipPath = explode('#', $path)[1];
|
||||
if ($zip->locateName($zipPath) !== false) {
|
||||
$this->path = $path;
|
||||
$this->setSizesAndType($path);
|
||||
}
|
||||
} else {
|
||||
throw new PhpSpreadsheetException("File $pValue not found!");
|
||||
throw new PhpSpreadsheetException("File $path not found!");
|
||||
}
|
||||
} else {
|
||||
$this->path = $pValue;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get isURL.
|
||||
*/
|
||||
public function getIsURL(): bool
|
||||
{
|
||||
return $this->isUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set isURL.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setIsURL(bool $isUrl): self
|
||||
{
|
||||
$this->isUrl = $isUrl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hash code.
|
||||
*
|
||||
@@ -111,4 +173,42 @@ class Drawing extends BaseDrawing
|
||||
__CLASS__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Image Type for Save.
|
||||
*/
|
||||
public function getImageTypeForSave(): int
|
||||
{
|
||||
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
return self::IMAGE_TYPES_CONVERTION_MAP[$this->type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Image file extention for Save.
|
||||
*/
|
||||
public function getImageFileExtensionForSave(bool $includeDot = true): string
|
||||
{
|
||||
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
$result = image_type_to_extension(self::IMAGE_TYPES_CONVERTION_MAP[$this->type], $includeDot);
|
||||
|
||||
return "$result";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Image mime type.
|
||||
*/
|
||||
public function getImageMimeType(): string
|
||||
{
|
||||
if (!array_key_exists($this->type, self::IMAGE_TYPES_CONVERTION_MAP)) {
|
||||
throw new PhpSpreadsheetException('Unsupported image type in comment background. Supported types: PNG, JPEG, BMP, GIF.');
|
||||
}
|
||||
|
||||
return image_type_to_mime_type(self::IMAGE_TYPES_CONVERTION_MAP[$this->type]);
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Shadow alignment.
|
||||
*
|
||||
* @var int
|
||||
* @var string
|
||||
*/
|
||||
private $alignment;
|
||||
|
||||
@@ -98,13 +98,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Visible.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $visible
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible($pValue)
|
||||
public function setVisible($visible)
|
||||
{
|
||||
$this->visible = $pValue;
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -122,13 +122,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Blur radius.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param int $blurRadius
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBlurRadius($pValue)
|
||||
public function setBlurRadius($blurRadius)
|
||||
{
|
||||
$this->blurRadius = $pValue;
|
||||
$this->blurRadius = $blurRadius;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -146,13 +146,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Shadow distance.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param int $distance
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDistance($pValue)
|
||||
public function setDistance($distance)
|
||||
{
|
||||
$this->distance = $pValue;
|
||||
$this->distance = $distance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -170,13 +170,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Shadow direction (in degrees).
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param int $direction
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDirection($pValue)
|
||||
public function setDirection($direction)
|
||||
{
|
||||
$this->direction = $pValue;
|
||||
$this->direction = $direction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -184,7 +184,7 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Get Shadow alignment.
|
||||
*
|
||||
* @return int
|
||||
* @return string
|
||||
*/
|
||||
public function getAlignment()
|
||||
{
|
||||
@@ -194,13 +194,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Shadow alignment.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param string $alignment
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlignment($pValue)
|
||||
public function setAlignment($alignment)
|
||||
{
|
||||
$this->alignment = $pValue;
|
||||
$this->alignment = $alignment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -218,13 +218,11 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Color.
|
||||
*
|
||||
* @param Color $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColor(?Color $pValue = null)
|
||||
public function setColor(?Color $color = null)
|
||||
{
|
||||
$this->color = $pValue;
|
||||
$this->color = $color;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -242,13 +240,13 @@ class Shadow implements IComparable
|
||||
/**
|
||||
* Set Alpha.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param int $alpha
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlpha($pValue)
|
||||
public function setAlpha($alpha)
|
||||
{
|
||||
$this->alpha = $pValue;
|
||||
$this->alpha = $alpha;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -170,13 +170,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set OddHeader.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $oddHeader
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOddHeader($pValue)
|
||||
public function setOddHeader($oddHeader)
|
||||
{
|
||||
$this->oddHeader = $pValue;
|
||||
$this->oddHeader = $oddHeader;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -194,13 +194,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set OddFooter.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $oddFooter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOddFooter($pValue)
|
||||
public function setOddFooter($oddFooter)
|
||||
{
|
||||
$this->oddFooter = $pValue;
|
||||
$this->oddFooter = $oddFooter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -218,13 +218,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set EvenHeader.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $eventHeader
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEvenHeader($pValue)
|
||||
public function setEvenHeader($eventHeader)
|
||||
{
|
||||
$this->evenHeader = $pValue;
|
||||
$this->evenHeader = $eventHeader;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -242,13 +242,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set EvenFooter.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $evenFooter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setEvenFooter($pValue)
|
||||
public function setEvenFooter($evenFooter)
|
||||
{
|
||||
$this->evenFooter = $pValue;
|
||||
$this->evenFooter = $evenFooter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -266,13 +266,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set FirstHeader.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $firstHeader
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstHeader($pValue)
|
||||
public function setFirstHeader($firstHeader)
|
||||
{
|
||||
$this->firstHeader = $pValue;
|
||||
$this->firstHeader = $firstHeader;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -290,13 +290,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set FirstFooter.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param string $firstFooter
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstFooter($pValue)
|
||||
public function setFirstFooter($firstFooter)
|
||||
{
|
||||
$this->firstFooter = $pValue;
|
||||
$this->firstFooter = $firstFooter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -314,13 +314,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set DifferentOddEven.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $differentOddEvent
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDifferentOddEven($pValue)
|
||||
public function setDifferentOddEven($differentOddEvent)
|
||||
{
|
||||
$this->differentOddEven = $pValue;
|
||||
$this->differentOddEven = $differentOddEvent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -338,13 +338,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set DifferentFirst.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $differentFirst
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDifferentFirst($pValue)
|
||||
public function setDifferentFirst($differentFirst)
|
||||
{
|
||||
$this->differentFirst = $pValue;
|
||||
$this->differentFirst = $differentFirst;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -362,13 +362,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set ScaleWithDocument.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $scaleWithDocument
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setScaleWithDocument($pValue)
|
||||
public function setScaleWithDocument($scaleWithDocument)
|
||||
{
|
||||
$this->scaleWithDocument = $pValue;
|
||||
$this->scaleWithDocument = $scaleWithDocument;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -386,13 +386,13 @@ class HeaderFooter
|
||||
/**
|
||||
* Set AlignWithMargins.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $alignWithMargins
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlignWithMargins($pValue)
|
||||
public function setAlignWithMargins($alignWithMargins)
|
||||
{
|
||||
$this->alignWithMargins = $pValue;
|
||||
$this->alignWithMargins = $alignWithMargins;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
|
||||
/**
|
||||
* @implements \Iterator<int, Worksheet>
|
||||
*/
|
||||
class Iterator implements \Iterator
|
||||
{
|
||||
/**
|
||||
@@ -29,14 +32,6 @@ class Iterator implements \Iterator
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->subject = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind iterator.
|
||||
*/
|
||||
@@ -47,20 +42,16 @@ class Iterator implements \Iterator
|
||||
|
||||
/**
|
||||
* Current Worksheet.
|
||||
*
|
||||
* @return Worksheet
|
||||
*/
|
||||
public function current()
|
||||
public function current(): Worksheet
|
||||
{
|
||||
return $this->subject->getSheet($this->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current key.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function key()
|
||||
public function key(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
@@ -75,10 +66,8 @@ class Iterator implements \Iterator
|
||||
|
||||
/**
|
||||
* Are there more Worksheet instances available?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->position < $this->subject->getSheetCount() && $this->position >= 0;
|
||||
}
|
||||
|
@@ -3,6 +3,8 @@
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use GdImage;
|
||||
use PhpOffice\PhpSpreadsheet\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\File;
|
||||
|
||||
class MemoryDrawing extends BaseDrawing
|
||||
{
|
||||
@@ -18,10 +20,16 @@ class MemoryDrawing extends BaseDrawing
|
||||
const MIMETYPE_GIF = 'image/gif';
|
||||
const MIMETYPE_JPEG = 'image/jpeg';
|
||||
|
||||
const SUPPORTED_MIME_TYPES = [
|
||||
self::MIMETYPE_GIF,
|
||||
self::MIMETYPE_JPEG,
|
||||
self::MIMETYPE_PNG,
|
||||
];
|
||||
|
||||
/**
|
||||
* Image resource.
|
||||
*
|
||||
* @var GdImage|resource
|
||||
* @var null|GdImage|resource
|
||||
*/
|
||||
private $imageResource;
|
||||
|
||||
@@ -46,25 +54,204 @@ class MemoryDrawing extends BaseDrawing
|
||||
*/
|
||||
private $uniqueName;
|
||||
|
||||
/** @var null|resource */
|
||||
private $alwaysNull;
|
||||
|
||||
/**
|
||||
* Create a new MemoryDrawing.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Initialise values
|
||||
$this->imageResource = null;
|
||||
$this->renderingFunction = self::RENDERING_DEFAULT;
|
||||
$this->mimeType = self::MIMETYPE_DEFAULT;
|
||||
$this->uniqueName = md5(mt_rand(0, 9999) . time() . mt_rand(0, 9999));
|
||||
$this->alwaysNull = null;
|
||||
|
||||
// Initialize parent
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->imageResource) {
|
||||
$rslt = @imagedestroy($this->imageResource);
|
||||
// "Fix" for Scrutinizer
|
||||
$this->imageResource = $rslt ? null : $this->alwaysNull;
|
||||
}
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
parent::__clone();
|
||||
$this->cloneResource();
|
||||
}
|
||||
|
||||
private function cloneResource(): void
|
||||
{
|
||||
if (!$this->imageResource) {
|
||||
return;
|
||||
}
|
||||
|
||||
$width = (int) imagesx($this->imageResource);
|
||||
$height = (int) imagesy($this->imageResource);
|
||||
|
||||
if (imageistruecolor($this->imageResource)) {
|
||||
$clone = imagecreatetruecolor($width, $height);
|
||||
if (!$clone) {
|
||||
throw new Exception('Could not clone image resource');
|
||||
}
|
||||
|
||||
imagealphablending($clone, false);
|
||||
imagesavealpha($clone, true);
|
||||
} else {
|
||||
$clone = imagecreate($width, $height);
|
||||
if (!$clone) {
|
||||
throw new Exception('Could not clone image resource');
|
||||
}
|
||||
|
||||
// If the image has transparency...
|
||||
$transparent = imagecolortransparent($this->imageResource);
|
||||
if ($transparent >= 0) {
|
||||
$rgb = imagecolorsforindex($this->imageResource, $transparent);
|
||||
if (empty($rgb)) {
|
||||
throw new Exception('Could not get image colors');
|
||||
}
|
||||
|
||||
imagesavealpha($clone, true);
|
||||
$color = imagecolorallocatealpha($clone, $rgb['red'], $rgb['green'], $rgb['blue'], $rgb['alpha']);
|
||||
if ($color === false) {
|
||||
throw new Exception('Could not get image alpha color');
|
||||
}
|
||||
|
||||
imagefill($clone, 0, 0, $color);
|
||||
}
|
||||
}
|
||||
|
||||
//Create the Clone!!
|
||||
imagecopy($clone, $this->imageResource, 0, 0, 0, 0, $width, $height);
|
||||
|
||||
$this->imageResource = $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource $imageStream Stream data to be converted to a Memory Drawing
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function fromStream($imageStream): self
|
||||
{
|
||||
$streamValue = stream_get_contents($imageStream);
|
||||
if ($streamValue === false) {
|
||||
throw new Exception('Unable to read data from stream');
|
||||
}
|
||||
|
||||
return self::fromString($streamValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $imageString String data to be converted to a Memory Drawing
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function fromString(string $imageString): self
|
||||
{
|
||||
$gdImage = @imagecreatefromstring($imageString);
|
||||
if ($gdImage === false) {
|
||||
throw new Exception('Value cannot be converted to an image');
|
||||
}
|
||||
|
||||
$mimeType = self::identifyMimeType($imageString);
|
||||
$renderingFunction = self::identifyRenderingFunction($mimeType);
|
||||
|
||||
$drawing = new self();
|
||||
$drawing->setImageResource($gdImage);
|
||||
$drawing->setRenderingFunction($renderingFunction);
|
||||
$drawing->setMimeType($mimeType);
|
||||
|
||||
return $drawing;
|
||||
}
|
||||
|
||||
private static function identifyRenderingFunction(string $mimeType): string
|
||||
{
|
||||
switch ($mimeType) {
|
||||
case self::MIMETYPE_PNG:
|
||||
return self::RENDERING_PNG;
|
||||
case self::MIMETYPE_JPEG:
|
||||
return self::RENDERING_JPEG;
|
||||
case self::MIMETYPE_GIF:
|
||||
return self::RENDERING_GIF;
|
||||
}
|
||||
|
||||
return self::RENDERING_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function identifyMimeType(string $imageString): string
|
||||
{
|
||||
$temporaryFileName = File::temporaryFilename();
|
||||
file_put_contents($temporaryFileName, $imageString);
|
||||
|
||||
$mimeType = self::identifyMimeTypeUsingExif($temporaryFileName);
|
||||
if ($mimeType !== null) {
|
||||
unlink($temporaryFileName);
|
||||
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
$mimeType = self::identifyMimeTypeUsingGd($temporaryFileName);
|
||||
if ($mimeType !== null) {
|
||||
unlink($temporaryFileName);
|
||||
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
unlink($temporaryFileName);
|
||||
|
||||
return self::MIMETYPE_DEFAULT;
|
||||
}
|
||||
|
||||
private static function identifyMimeTypeUsingExif(string $temporaryFileName): ?string
|
||||
{
|
||||
if (function_exists('exif_imagetype')) {
|
||||
$imageType = @exif_imagetype($temporaryFileName);
|
||||
$mimeType = ($imageType) ? image_type_to_mime_type($imageType) : null;
|
||||
|
||||
return self::supportedMimeTypes($mimeType);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function identifyMimeTypeUsingGd(string $temporaryFileName): ?string
|
||||
{
|
||||
if (function_exists('getimagesize')) {
|
||||
$imageSize = @getimagesize($temporaryFileName);
|
||||
if (is_array($imageSize)) {
|
||||
$mimeType = $imageSize['mime'] ?? null;
|
||||
|
||||
return self::supportedMimeTypes($mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function supportedMimeTypes(?string $mimeType = null): ?string
|
||||
{
|
||||
if (in_array($mimeType, self::SUPPORTED_MIME_TYPES, true)) {
|
||||
return $mimeType;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image resource.
|
||||
*
|
||||
* @return GdImage|resource
|
||||
* @return null|GdImage|resource
|
||||
*/
|
||||
public function getImageResource()
|
||||
{
|
||||
@@ -84,8 +271,8 @@ class MemoryDrawing extends BaseDrawing
|
||||
|
||||
if ($this->imageResource !== null) {
|
||||
// Get width/height
|
||||
$this->width = imagesx($this->imageResource);
|
||||
$this->height = imagesy($this->imageResource);
|
||||
$this->width = (int) imagesx($this->imageResource);
|
||||
$this->height = (int) imagesy($this->imageResource);
|
||||
}
|
||||
|
||||
return $this;
|
||||
@@ -141,10 +328,8 @@ class MemoryDrawing extends BaseDrawing
|
||||
|
||||
/**
|
||||
* Get indexed filename (using image index).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIndexedFilename()
|
||||
public function getIndexedFilename(): string
|
||||
{
|
||||
$extension = strtolower($this->getMimeType());
|
||||
$extension = explode('/', $extension);
|
||||
|
@@ -66,13 +66,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Left.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $left
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setLeft($pValue)
|
||||
public function setLeft($left)
|
||||
{
|
||||
$this->left = $pValue;
|
||||
$this->left = $left;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -90,13 +90,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Right.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $right
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRight($pValue)
|
||||
public function setRight($right)
|
||||
{
|
||||
$this->right = $pValue;
|
||||
$this->right = $right;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -114,13 +114,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Top.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $top
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTop($pValue)
|
||||
public function setTop($top)
|
||||
{
|
||||
$this->top = $pValue;
|
||||
$this->top = $top;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -138,13 +138,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Bottom.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $bottom
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottom($pValue)
|
||||
public function setBottom($bottom)
|
||||
{
|
||||
$this->bottom = $pValue;
|
||||
$this->bottom = $bottom;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -162,13 +162,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Header.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $header
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeader($pValue)
|
||||
public function setHeader($header)
|
||||
{
|
||||
$this->header = $pValue;
|
||||
$this->header = $header;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -186,13 +186,13 @@ class PageMargins
|
||||
/**
|
||||
* Set Footer.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $footer
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFooter($pValue)
|
||||
public function setFooter($footer)
|
||||
{
|
||||
$this->footer = $pValue;
|
||||
$this->footer = $footer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -160,18 +160,32 @@ class PageSetup
|
||||
const PAGEORDER_DOWN_THEN_OVER = 'downThenOver';
|
||||
|
||||
/**
|
||||
* Paper size.
|
||||
* Paper size default.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $paperSize = self::PAPERSIZE_LETTER;
|
||||
private static $paperSizeDefault = self::PAPERSIZE_LETTER;
|
||||
|
||||
/**
|
||||
* Paper size.
|
||||
*
|
||||
* @var ?int
|
||||
*/
|
||||
private $paperSize;
|
||||
|
||||
/**
|
||||
* Orientation default.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $orientationDefault = self::ORIENTATION_DEFAULT;
|
||||
|
||||
/**
|
||||
* Orientation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $orientation = self::ORIENTATION_DEFAULT;
|
||||
private $orientation;
|
||||
|
||||
/**
|
||||
* Scale (Print Scale).
|
||||
@@ -238,17 +252,18 @@ class PageSetup
|
||||
/**
|
||||
* Print area.
|
||||
*
|
||||
* @var string
|
||||
* @var null|string
|
||||
*/
|
||||
private $printArea;
|
||||
|
||||
/**
|
||||
* First page number.
|
||||
*
|
||||
* @var int
|
||||
* @var ?int
|
||||
*/
|
||||
private $firstPageNumber;
|
||||
|
||||
/** @var string */
|
||||
private $pageOrder = self::PAGEORDER_DOWN_THEN_OVER;
|
||||
|
||||
/**
|
||||
@@ -256,6 +271,7 @@ class PageSetup
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->orientation = self::$orientationDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,23 +281,39 @@ class PageSetup
|
||||
*/
|
||||
public function getPaperSize()
|
||||
{
|
||||
return $this->paperSize;
|
||||
return $this->paperSize ?? self::$paperSizeDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paper Size.
|
||||
*
|
||||
* @param int $pValue see self::PAPERSIZE_*
|
||||
* @param int $paperSize see self::PAPERSIZE_*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPaperSize($pValue)
|
||||
public function setPaperSize($paperSize)
|
||||
{
|
||||
$this->paperSize = $pValue;
|
||||
$this->paperSize = $paperSize;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Paper Size default.
|
||||
*/
|
||||
public static function getPaperSizeDefault(): int
|
||||
{
|
||||
return self::$paperSizeDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Paper Size Default.
|
||||
*/
|
||||
public static function setPaperSizeDefault(int $paperSize): void
|
||||
{
|
||||
self::$paperSizeDefault = $paperSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Orientation.
|
||||
*
|
||||
@@ -295,17 +327,31 @@ class PageSetup
|
||||
/**
|
||||
* Set Orientation.
|
||||
*
|
||||
* @param string $pValue see self::ORIENTATION_*
|
||||
* @param string $orientation see self::ORIENTATION_*
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrientation($pValue)
|
||||
public function setOrientation($orientation)
|
||||
{
|
||||
$this->orientation = $pValue;
|
||||
if ($orientation === self::ORIENTATION_LANDSCAPE || $orientation === self::ORIENTATION_PORTRAIT || $orientation === self::ORIENTATION_DEFAULT) {
|
||||
$this->orientation = $orientation;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function getOrientationDefault(): string
|
||||
{
|
||||
return self::$orientationDefault;
|
||||
}
|
||||
|
||||
public static function setOrientationDefault(string $orientation): void
|
||||
{
|
||||
if ($orientation === self::ORIENTATION_LANDSCAPE || $orientation === self::ORIENTATION_PORTRAIT || $orientation === self::ORIENTATION_DEFAULT) {
|
||||
self::$orientationDefault = $orientation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Scale.
|
||||
*
|
||||
@@ -321,18 +367,18 @@ class PageSetup
|
||||
* Print scaling. Valid values range from 10 to 400
|
||||
* This setting is overridden when fitToWidth and/or fitToHeight are in use.
|
||||
*
|
||||
* @param null|int $pValue
|
||||
* @param bool $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth
|
||||
* @param null|int $scale
|
||||
* @param bool $update Update fitToPage so scaling applies rather than fitToHeight / fitToWidth
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setScale($pValue, $pUpdate = true)
|
||||
public function setScale($scale, $update = true)
|
||||
{
|
||||
// Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface,
|
||||
// but it is apparently still able to handle any scale >= 0, where 0 results in 100
|
||||
if (($pValue >= 0) || $pValue === null) {
|
||||
$this->scale = $pValue;
|
||||
if ($pUpdate) {
|
||||
if ($scale === null || $scale >= 0) {
|
||||
$this->scale = $scale;
|
||||
if ($update) {
|
||||
$this->fitToPage = false;
|
||||
}
|
||||
} else {
|
||||
@@ -355,13 +401,13 @@ class PageSetup
|
||||
/**
|
||||
* Set Fit To Page.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $fitToPage
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToPage($pValue)
|
||||
public function setFitToPage($fitToPage)
|
||||
{
|
||||
$this->fitToPage = $pValue;
|
||||
$this->fitToPage = $fitToPage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -379,15 +425,15 @@ class PageSetup
|
||||
/**
|
||||
* Set Fit To Height.
|
||||
*
|
||||
* @param null|int $pValue
|
||||
* @param bool $pUpdate Update fitToPage so it applies rather than scaling
|
||||
* @param null|int $fitToHeight
|
||||
* @param bool $update Update fitToPage so it applies rather than scaling
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToHeight($pValue, $pUpdate = true)
|
||||
public function setFitToHeight($fitToHeight, $update = true)
|
||||
{
|
||||
$this->fitToHeight = $pValue;
|
||||
if ($pUpdate) {
|
||||
$this->fitToHeight = $fitToHeight;
|
||||
if ($update) {
|
||||
$this->fitToPage = true;
|
||||
}
|
||||
|
||||
@@ -407,15 +453,15 @@ class PageSetup
|
||||
/**
|
||||
* Set Fit To Width.
|
||||
*
|
||||
* @param null|int $pValue
|
||||
* @param bool $pUpdate Update fitToPage so it applies rather than scaling
|
||||
* @param null|int $value
|
||||
* @param bool $update Update fitToPage so it applies rather than scaling
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToWidth($pValue, $pUpdate = true)
|
||||
public function setFitToWidth($value, $update = true)
|
||||
{
|
||||
$this->fitToWidth = $pValue;
|
||||
if ($pUpdate) {
|
||||
$this->fitToWidth = $value;
|
||||
if ($update) {
|
||||
$this->fitToPage = true;
|
||||
}
|
||||
|
||||
@@ -429,7 +475,7 @@ class PageSetup
|
||||
*/
|
||||
public function isColumnsToRepeatAtLeftSet()
|
||||
{
|
||||
if (is_array($this->columnsToRepeatAtLeft)) {
|
||||
if (!empty($this->columnsToRepeatAtLeft)) {
|
||||
if ($this->columnsToRepeatAtLeft[0] != '' && $this->columnsToRepeatAtLeft[1] != '') {
|
||||
return true;
|
||||
}
|
||||
@@ -451,13 +497,13 @@ class PageSetup
|
||||
/**
|
||||
* Set Columns to repeat at left.
|
||||
*
|
||||
* @param array $pValue Containing start column and end column, empty array if option unset
|
||||
* @param array $columnsToRepeatAtLeft Containing start column and end column, empty array if option unset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnsToRepeatAtLeft(array $pValue)
|
||||
public function setColumnsToRepeatAtLeft(array $columnsToRepeatAtLeft)
|
||||
{
|
||||
$this->columnsToRepeatAtLeft = $pValue;
|
||||
$this->columnsToRepeatAtLeft = $columnsToRepeatAtLeft;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -465,14 +511,14 @@ class PageSetup
|
||||
/**
|
||||
* Set Columns to repeat at left by start and end.
|
||||
*
|
||||
* @param string $pStart eg: 'A'
|
||||
* @param string $pEnd eg: 'B'
|
||||
* @param string $start eg: 'A'
|
||||
* @param string $end eg: 'B'
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnsToRepeatAtLeftByStartAndEnd($pStart, $pEnd)
|
||||
public function setColumnsToRepeatAtLeftByStartAndEnd($start, $end)
|
||||
{
|
||||
$this->columnsToRepeatAtLeft = [$pStart, $pEnd];
|
||||
$this->columnsToRepeatAtLeft = [$start, $end];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -484,7 +530,7 @@ class PageSetup
|
||||
*/
|
||||
public function isRowsToRepeatAtTopSet()
|
||||
{
|
||||
if (is_array($this->rowsToRepeatAtTop)) {
|
||||
if (!empty($this->rowsToRepeatAtTop)) {
|
||||
if ($this->rowsToRepeatAtTop[0] != 0 && $this->rowsToRepeatAtTop[1] != 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -506,13 +552,13 @@ class PageSetup
|
||||
/**
|
||||
* Set Rows to repeat at top.
|
||||
*
|
||||
* @param array $pValue Containing start column and end column, empty array if option unset
|
||||
* @param array $rowsToRepeatAtTop Containing start column and end column, empty array if option unset
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowsToRepeatAtTop(array $pValue)
|
||||
public function setRowsToRepeatAtTop(array $rowsToRepeatAtTop)
|
||||
{
|
||||
$this->rowsToRepeatAtTop = $pValue;
|
||||
$this->rowsToRepeatAtTop = $rowsToRepeatAtTop;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -520,14 +566,14 @@ class PageSetup
|
||||
/**
|
||||
* Set Rows to repeat at top by start and end.
|
||||
*
|
||||
* @param int $pStart eg: 1
|
||||
* @param int $pEnd eg: 1
|
||||
* @param int $start eg: 1
|
||||
* @param int $end eg: 1
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowsToRepeatAtTopByStartAndEnd($pStart, $pEnd)
|
||||
public function setRowsToRepeatAtTopByStartAndEnd($start, $end)
|
||||
{
|
||||
$this->rowsToRepeatAtTop = [$pStart, $pEnd];
|
||||
$this->rowsToRepeatAtTop = [$start, $end];
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -595,7 +641,7 @@ class PageSetup
|
||||
if ($index == 0) {
|
||||
return $this->printArea;
|
||||
}
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
$printAreas = explode(',', (string) $this->printArea);
|
||||
if (isset($printAreas[$index - 1])) {
|
||||
return $printAreas[$index - 1];
|
||||
}
|
||||
@@ -618,7 +664,7 @@ class PageSetup
|
||||
if ($index == 0) {
|
||||
return $this->printArea !== null;
|
||||
}
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
$printAreas = explode(',', (string) $this->printArea);
|
||||
|
||||
return isset($printAreas[$index - 1]);
|
||||
}
|
||||
@@ -638,7 +684,7 @@ class PageSetup
|
||||
if ($index == 0) {
|
||||
$this->printArea = null;
|
||||
} else {
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
$printAreas = explode(',', (string) $this->printArea);
|
||||
if (isset($printAreas[$index - 1])) {
|
||||
unset($printAreas[$index - 1]);
|
||||
$this->printArea = implode(',', $printAreas);
|
||||
@@ -686,7 +732,7 @@ class PageSetup
|
||||
if ($index == 0) {
|
||||
$this->printArea = $value;
|
||||
} else {
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
$printAreas = explode(',', (string) $this->printArea);
|
||||
if ($index < 0) {
|
||||
$index = count($printAreas) - abs($index) + 1;
|
||||
}
|
||||
@@ -700,9 +746,9 @@ class PageSetup
|
||||
if ($index == 0) {
|
||||
$this->printArea = $this->printArea ? ($this->printArea . ',' . $value) : $value;
|
||||
} else {
|
||||
$printAreas = explode(',', $this->printArea);
|
||||
$printAreas = explode(',', (string) $this->printArea);
|
||||
if ($index < 0) {
|
||||
$index = abs($index) - 1;
|
||||
$index = (int) abs($index) - 1;
|
||||
}
|
||||
if ($index > count($printAreas)) {
|
||||
throw new PhpSpreadsheetException('Invalid index for setting print range.');
|
||||
@@ -795,7 +841,7 @@ class PageSetup
|
||||
/**
|
||||
* Get first page number.
|
||||
*
|
||||
* @return int
|
||||
* @return ?int
|
||||
*/
|
||||
public function getFirstPageNumber()
|
||||
{
|
||||
@@ -805,7 +851,7 @@ class PageSetup
|
||||
/**
|
||||
* Set first page number.
|
||||
*
|
||||
* @param int $value
|
||||
* @param ?int $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
|
@@ -18,116 +18,116 @@ class Protection
|
||||
const ALGORITHM_WHIRLPOOL = 'WHIRLPOOL';
|
||||
|
||||
/**
|
||||
* Sheet.
|
||||
* Autofilters are locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $sheet = false;
|
||||
private $autoFilter;
|
||||
|
||||
/**
|
||||
* Objects.
|
||||
* Deleting columns is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $objects = false;
|
||||
private $deleteColumns;
|
||||
|
||||
/**
|
||||
* Scenarios.
|
||||
* Deleting rows is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $scenarios = false;
|
||||
private $deleteRows;
|
||||
|
||||
/**
|
||||
* Format cells.
|
||||
* Formatting cells is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $formatCells = false;
|
||||
private $formatCells;
|
||||
|
||||
/**
|
||||
* Format columns.
|
||||
* Formatting columns is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $formatColumns = false;
|
||||
private $formatColumns;
|
||||
|
||||
/**
|
||||
* Format rows.
|
||||
* Formatting rows is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $formatRows = false;
|
||||
private $formatRows;
|
||||
|
||||
/**
|
||||
* Insert columns.
|
||||
* Inserting columns is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $insertColumns = false;
|
||||
private $insertColumns;
|
||||
|
||||
/**
|
||||
* Insert rows.
|
||||
* Inserting hyperlinks is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $insertRows = false;
|
||||
private $insertHyperlinks;
|
||||
|
||||
/**
|
||||
* Insert hyperlinks.
|
||||
* Inserting rows is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $insertHyperlinks = false;
|
||||
private $insertRows;
|
||||
|
||||
/**
|
||||
* Delete columns.
|
||||
* Objects are locked when sheet is protected, default false.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $deleteColumns = false;
|
||||
private $objects;
|
||||
|
||||
/**
|
||||
* Delete rows.
|
||||
* Pivot tables are locked when the sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $deleteRows = false;
|
||||
private $pivotTables;
|
||||
|
||||
/**
|
||||
* Select locked cells.
|
||||
* Scenarios are locked when sheet is protected, default false.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $selectLockedCells = false;
|
||||
private $scenarios;
|
||||
|
||||
/**
|
||||
* Sort.
|
||||
* Selection of locked cells is locked when sheet is protected, default false.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $sort = false;
|
||||
private $selectLockedCells;
|
||||
|
||||
/**
|
||||
* AutoFilter.
|
||||
* Selection of unlocked cells is locked when sheet is protected, default false.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $autoFilter = false;
|
||||
private $selectUnlockedCells;
|
||||
|
||||
/**
|
||||
* Pivot tables.
|
||||
* Sheet is locked when sheet is protected, default false.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $pivotTables = false;
|
||||
private $sheet;
|
||||
|
||||
/**
|
||||
* Select unlocked cells.
|
||||
* Sorting is locked when sheet is protected, default true.
|
||||
*
|
||||
* @var bool
|
||||
* @var ?bool
|
||||
*/
|
||||
private $selectUnlockedCells = false;
|
||||
private $sort;
|
||||
|
||||
/**
|
||||
* Hashed password.
|
||||
@@ -166,409 +166,217 @@ class Protection
|
||||
|
||||
/**
|
||||
* Is some sort of protection enabled?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isProtectionEnabled()
|
||||
public function isProtectionEnabled(): bool
|
||||
{
|
||||
return $this->sheet ||
|
||||
$this->objects ||
|
||||
$this->scenarios ||
|
||||
$this->formatCells ||
|
||||
$this->formatColumns ||
|
||||
$this->formatRows ||
|
||||
$this->insertColumns ||
|
||||
$this->insertRows ||
|
||||
$this->insertHyperlinks ||
|
||||
$this->deleteColumns ||
|
||||
$this->deleteRows ||
|
||||
$this->selectLockedCells ||
|
||||
$this->sort ||
|
||||
$this->autoFilter ||
|
||||
$this->pivotTables ||
|
||||
$this->selectUnlockedCells;
|
||||
return
|
||||
$this->password !== '' ||
|
||||
isset($this->sheet) ||
|
||||
isset($this->objects) ||
|
||||
isset($this->scenarios) ||
|
||||
isset($this->formatCells) ||
|
||||
isset($this->formatColumns) ||
|
||||
isset($this->formatRows) ||
|
||||
isset($this->insertColumns) ||
|
||||
isset($this->insertRows) ||
|
||||
isset($this->insertHyperlinks) ||
|
||||
isset($this->deleteColumns) ||
|
||||
isset($this->deleteRows) ||
|
||||
isset($this->selectLockedCells) ||
|
||||
isset($this->sort) ||
|
||||
isset($this->autoFilter) ||
|
||||
isset($this->pivotTables) ||
|
||||
isset($this->selectUnlockedCells);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sheet.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSheet()
|
||||
public function getSheet(): ?bool
|
||||
{
|
||||
return $this->sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Sheet.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheet($pValue)
|
||||
public function setSheet(?bool $sheet): self
|
||||
{
|
||||
$this->sheet = $pValue;
|
||||
$this->sheet = $sheet;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Objects.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getObjects()
|
||||
public function getObjects(): ?bool
|
||||
{
|
||||
return $this->objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Objects.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setObjects($pValue)
|
||||
public function setObjects(?bool $objects): self
|
||||
{
|
||||
$this->objects = $pValue;
|
||||
$this->objects = $objects;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Scenarios.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getScenarios()
|
||||
public function getScenarios(): ?bool
|
||||
{
|
||||
return $this->scenarios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Scenarios.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setScenarios($pValue)
|
||||
public function setScenarios(?bool $scenarios): self
|
||||
{
|
||||
$this->scenarios = $pValue;
|
||||
$this->scenarios = $scenarios;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FormatCells.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getFormatCells()
|
||||
public function getFormatCells(): ?bool
|
||||
{
|
||||
return $this->formatCells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set FormatCells.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatCells($pValue)
|
||||
public function setFormatCells(?bool $formatCells): self
|
||||
{
|
||||
$this->formatCells = $pValue;
|
||||
$this->formatCells = $formatCells;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FormatColumns.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getFormatColumns()
|
||||
public function getFormatColumns(): ?bool
|
||||
{
|
||||
return $this->formatColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set FormatColumns.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatColumns($pValue)
|
||||
public function setFormatColumns(?bool $formatColumns): self
|
||||
{
|
||||
$this->formatColumns = $pValue;
|
||||
$this->formatColumns = $formatColumns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FormatRows.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getFormatRows()
|
||||
public function getFormatRows(): ?bool
|
||||
{
|
||||
return $this->formatRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set FormatRows.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatRows($pValue)
|
||||
public function setFormatRows(?bool $formatRows): self
|
||||
{
|
||||
$this->formatRows = $pValue;
|
||||
$this->formatRows = $formatRows;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get InsertColumns.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getInsertColumns()
|
||||
public function getInsertColumns(): ?bool
|
||||
{
|
||||
return $this->insertColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set InsertColumns.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertColumns($pValue)
|
||||
public function setInsertColumns(?bool $insertColumns): self
|
||||
{
|
||||
$this->insertColumns = $pValue;
|
||||
$this->insertColumns = $insertColumns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get InsertRows.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getInsertRows()
|
||||
public function getInsertRows(): ?bool
|
||||
{
|
||||
return $this->insertRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set InsertRows.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertRows($pValue)
|
||||
public function setInsertRows(?bool $insertRows): self
|
||||
{
|
||||
$this->insertRows = $pValue;
|
||||
$this->insertRows = $insertRows;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get InsertHyperlinks.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getInsertHyperlinks()
|
||||
public function getInsertHyperlinks(): ?bool
|
||||
{
|
||||
return $this->insertHyperlinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set InsertHyperlinks.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertHyperlinks($pValue)
|
||||
public function setInsertHyperlinks(?bool $insertHyperLinks): self
|
||||
{
|
||||
$this->insertHyperlinks = $pValue;
|
||||
$this->insertHyperlinks = $insertHyperLinks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get DeleteColumns.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDeleteColumns()
|
||||
public function getDeleteColumns(): ?bool
|
||||
{
|
||||
return $this->deleteColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DeleteColumns.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDeleteColumns($pValue)
|
||||
public function setDeleteColumns(?bool $deleteColumns): self
|
||||
{
|
||||
$this->deleteColumns = $pValue;
|
||||
$this->deleteColumns = $deleteColumns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get DeleteRows.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDeleteRows()
|
||||
public function getDeleteRows(): ?bool
|
||||
{
|
||||
return $this->deleteRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DeleteRows.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setDeleteRows($pValue)
|
||||
public function setDeleteRows(?bool $deleteRows): self
|
||||
{
|
||||
$this->deleteRows = $pValue;
|
||||
$this->deleteRows = $deleteRows;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SelectLockedCells.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSelectLockedCells()
|
||||
public function getSelectLockedCells(): ?bool
|
||||
{
|
||||
return $this->selectLockedCells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SelectLockedCells.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectLockedCells($pValue)
|
||||
public function setSelectLockedCells(?bool $selectLockedCells): self
|
||||
{
|
||||
$this->selectLockedCells = $pValue;
|
||||
$this->selectLockedCells = $selectLockedCells;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sort.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSort()
|
||||
public function getSort(): ?bool
|
||||
{
|
||||
return $this->sort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Sort.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSort($pValue)
|
||||
public function setSort(?bool $sort): self
|
||||
{
|
||||
$this->sort = $pValue;
|
||||
$this->sort = $sort;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AutoFilter.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getAutoFilter()
|
||||
public function getAutoFilter(): ?bool
|
||||
{
|
||||
return $this->autoFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AutoFilter.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoFilter($pValue)
|
||||
public function setAutoFilter(?bool $autoFilter): self
|
||||
{
|
||||
$this->autoFilter = $pValue;
|
||||
$this->autoFilter = $autoFilter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get PivotTables.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getPivotTables()
|
||||
public function getPivotTables(): ?bool
|
||||
{
|
||||
return $this->pivotTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PivotTables.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPivotTables($pValue)
|
||||
public function setPivotTables(?bool $pivotTables): self
|
||||
{
|
||||
$this->pivotTables = $pValue;
|
||||
$this->pivotTables = $pivotTables;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SelectUnlockedCells.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getSelectUnlockedCells()
|
||||
public function getSelectUnlockedCells(): ?bool
|
||||
{
|
||||
return $this->selectUnlockedCells;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set SelectUnlockedCells.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectUnlockedCells($pValue)
|
||||
public function setSelectUnlockedCells(?bool $selectUnlockedCells): self
|
||||
{
|
||||
$this->selectUnlockedCells = $pValue;
|
||||
$this->selectUnlockedCells = $selectUnlockedCells;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -586,24 +394,29 @@ class Protection
|
||||
/**
|
||||
* Set Password.
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param bool $pAlreadyHashed If the password has already been hashed, set this to true
|
||||
* @param string $password
|
||||
* @param bool $alreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setPassword($pValue, $pAlreadyHashed = false)
|
||||
public function setPassword($password, $alreadyHashed = false)
|
||||
{
|
||||
if (!$pAlreadyHashed) {
|
||||
if (!$alreadyHashed) {
|
||||
$salt = $this->generateSalt();
|
||||
$this->setSalt($salt);
|
||||
$pValue = PasswordHasher::hashPassword($pValue, $this->getAlgorithm(), $this->getSalt(), $this->getSpinCount());
|
||||
$password = PasswordHasher::hashPassword($password, $this->getAlgorithm(), $this->getSalt(), $this->getSpinCount());
|
||||
}
|
||||
|
||||
$this->password = $pValue;
|
||||
$this->password = $password;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHashValue(string $password): self
|
||||
{
|
||||
return $this->setPassword($password, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pseudorandom string.
|
||||
*/
|
||||
@@ -623,25 +436,36 @@ class Protection
|
||||
/**
|
||||
* Set algorithm name.
|
||||
*/
|
||||
public function setAlgorithm(string $algorithm): void
|
||||
public function setAlgorithm(string $algorithm): self
|
||||
{
|
||||
$this->algorithm = $algorithm;
|
||||
return $this->setAlgorithmName($algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get salt value.
|
||||
* Set algorithm name.
|
||||
*/
|
||||
public function setAlgorithmName(string $algorithm): self
|
||||
{
|
||||
$this->algorithm = $algorithm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSalt(): string
|
||||
{
|
||||
return $this->salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set salt value.
|
||||
*/
|
||||
public function setSalt(string $salt): void
|
||||
public function setSalt(string $salt): self
|
||||
{
|
||||
return $this->setSaltValue($salt);
|
||||
}
|
||||
|
||||
public function setSaltValue(string $salt): self
|
||||
{
|
||||
$this->salt = $salt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -655,9 +479,11 @@ class Protection
|
||||
/**
|
||||
* Set spin count.
|
||||
*/
|
||||
public function setSpinCount(int $spinCount): void
|
||||
public function setSpinCount(int $spinCount): self
|
||||
{
|
||||
$this->spinCount = $spinCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,7 +491,7 @@ class Protection
|
||||
*/
|
||||
public function verify(string $password): bool
|
||||
{
|
||||
if (!$this->isProtectionEnabled()) {
|
||||
if ($this->password === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -21,10 +21,9 @@ class Row
|
||||
/**
|
||||
* Create a new row.
|
||||
*
|
||||
* @param Worksheet $worksheet
|
||||
* @param int $rowIndex
|
||||
*/
|
||||
public function __construct(?Worksheet $worksheet = null, $rowIndex = 1)
|
||||
public function __construct(Worksheet $worksheet, $rowIndex = 1)
|
||||
{
|
||||
// Set parent and row index
|
||||
$this->worksheet = $worksheet;
|
||||
@@ -36,15 +35,13 @@ class Row
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->worksheet = null;
|
||||
$this->worksheet = null; // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
/**
|
||||
* Get row index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRowIndex()
|
||||
public function getRowIndex(): int
|
||||
{
|
||||
return $this->rowIndex;
|
||||
}
|
||||
@@ -63,11 +60,49 @@ class Row
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bound worksheet.
|
||||
* Returns a boolean true if the row contains no cells. By default, this means that no cell records exist in the
|
||||
* collection for this row. false will be returned otherwise.
|
||||
* This rule can be modified by passing a $definitionOfEmptyFlags value:
|
||||
* 1 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL If the only cells in the collection are null value
|
||||
* cells, then the row will be considered empty.
|
||||
* 2 - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL If the only cells in the collection are empty
|
||||
* string value cells, then the row will be considered empty.
|
||||
* 3 - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL | CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||
* If the only cells in the collection are null value or empty string value cells, then the row
|
||||
* will be considered empty.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @param int $definitionOfEmptyFlags
|
||||
* Possible Flag Values are:
|
||||
* CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL
|
||||
* CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL
|
||||
*/
|
||||
public function getWorksheet()
|
||||
public function isEmpty(int $definitionOfEmptyFlags = 0): bool
|
||||
{
|
||||
$nullValueCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL);
|
||||
$emptyStringCellIsEmpty = (bool) ($definitionOfEmptyFlags & CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL);
|
||||
|
||||
$cellIterator = $this->getCellIterator();
|
||||
$cellIterator->setIterateOnlyExistingCells(true);
|
||||
foreach ($cellIterator as $cell) {
|
||||
/** @scrutinizer ignore-call */
|
||||
$value = $cell->getValue();
|
||||
if ($value === null && $nullValueCellIsEmpty === true) {
|
||||
continue;
|
||||
}
|
||||
if ($value === '' && $emptyStringCellIsEmpty === true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bound worksheet.
|
||||
*/
|
||||
public function getWorksheet(): Worksheet
|
||||
{
|
||||
return $this->worksheet;
|
||||
}
|
||||
|
@@ -2,9 +2,13 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
/**
|
||||
* @extends CellIterator<string>
|
||||
*/
|
||||
class RowCellIterator extends CellIterator
|
||||
{
|
||||
/**
|
||||
@@ -43,10 +47,11 @@ class RowCellIterator extends CellIterator
|
||||
* @param string $startColumn The column address at which to start iterating
|
||||
* @param string $endColumn Optionally, the column address at which to stop iterating
|
||||
*/
|
||||
public function __construct(?Worksheet $worksheet = null, $rowIndex = 1, $startColumn = 'A', $endColumn = null)
|
||||
public function __construct(Worksheet $worksheet, $rowIndex = 1, $startColumn = 'A', $endColumn = null)
|
||||
{
|
||||
// Set subject and row index
|
||||
$this->worksheet = $worksheet;
|
||||
$this->cellCollection = $worksheet->getCellCollection();
|
||||
$this->rowIndex = $rowIndex;
|
||||
$this->resetEnd($endColumn);
|
||||
$this->resetStart($startColumn);
|
||||
@@ -59,7 +64,7 @@ class RowCellIterator extends CellIterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startColumn = 'A')
|
||||
public function resetStart(string $startColumn = 'A')
|
||||
{
|
||||
$this->startColumnIndex = Coordinate::columnIndexFromString($startColumn);
|
||||
$this->adjustForExistingOnlyRange();
|
||||
@@ -77,7 +82,7 @@ class RowCellIterator extends CellIterator
|
||||
*/
|
||||
public function resetEnd($endColumn = null)
|
||||
{
|
||||
$endColumn = $endColumn ? $endColumn : $this->worksheet->getHighestColumn();
|
||||
$endColumn = $endColumn ?: $this->worksheet->getHighestColumn();
|
||||
$this->endColumnIndex = Coordinate::columnIndexFromString($endColumn);
|
||||
$this->adjustForExistingOnlyRange();
|
||||
|
||||
@@ -91,17 +96,16 @@ class RowCellIterator extends CellIterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($column = 'A')
|
||||
public function seek(string $column = 'A')
|
||||
{
|
||||
$columnx = $column;
|
||||
$column = Coordinate::columnIndexFromString($column);
|
||||
if ($this->onlyExistingCells && !($this->worksheet->cellExistsByColumnAndRow($column, $this->rowIndex))) {
|
||||
$columnId = Coordinate::columnIndexFromString($column);
|
||||
if ($this->onlyExistingCells && !($this->cellCollection->has($column . $this->rowIndex))) {
|
||||
throw new PhpSpreadsheetException('In "IterateOnlyExistingCells" mode and Cell does not exist');
|
||||
}
|
||||
if (($column < $this->startColumnIndex) || ($column > $this->endColumnIndex)) {
|
||||
throw new PhpSpreadsheetException("Column $columnx is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
|
||||
if (($columnId < $this->startColumnIndex) || ($columnId > $this->endColumnIndex)) {
|
||||
throw new PhpSpreadsheetException("Column $column is out of range ({$this->startColumnIndex} - {$this->endColumnIndex})");
|
||||
}
|
||||
$this->currentColumnIndex = $column;
|
||||
$this->currentColumnIndex = $columnId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -116,20 +120,20 @@ class RowCellIterator extends CellIterator
|
||||
|
||||
/**
|
||||
* Return the current cell in this worksheet row.
|
||||
*
|
||||
* @return \PhpOffice\PhpSpreadsheet\Cell\Cell
|
||||
*/
|
||||
public function current()
|
||||
public function current(): ?Cell
|
||||
{
|
||||
return $this->worksheet->getCellByColumnAndRow($this->currentColumnIndex, $this->rowIndex);
|
||||
$cellAddress = Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex;
|
||||
|
||||
return $this->cellCollection->has($cellAddress)
|
||||
? $this->cellCollection->get($cellAddress)
|
||||
: $this->worksheet->createNewCell($cellAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current iterator key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function key()
|
||||
public function key(): string
|
||||
{
|
||||
return Coordinate::stringFromColumnIndex($this->currentColumnIndex);
|
||||
}
|
||||
@@ -141,7 +145,7 @@ class RowCellIterator extends CellIterator
|
||||
{
|
||||
do {
|
||||
++$this->currentColumnIndex;
|
||||
} while (($this->onlyExistingCells) && (!$this->worksheet->cellExistsByColumnAndRow($this->currentColumnIndex, $this->rowIndex)) && ($this->currentColumnIndex <= $this->endColumnIndex));
|
||||
} while (($this->onlyExistingCells) && (!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex)) && ($this->currentColumnIndex <= $this->endColumnIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,25 +155,21 @@ class RowCellIterator extends CellIterator
|
||||
{
|
||||
do {
|
||||
--$this->currentColumnIndex;
|
||||
} while (($this->onlyExistingCells) && (!$this->worksheet->cellExistsByColumnAndRow($this->currentColumnIndex, $this->rowIndex)) && ($this->currentColumnIndex >= $this->startColumnIndex));
|
||||
} while (($this->onlyExistingCells) && (!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->currentColumnIndex) . $this->rowIndex)) && ($this->currentColumnIndex >= $this->startColumnIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if more columns exist in the worksheet range of columns that we're iterating.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->currentColumnIndex <= $this->endColumnIndex && $this->currentColumnIndex >= $this->startColumnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current iterator position.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrentColumnIndex()
|
||||
public function getCurrentColumnIndex(): int
|
||||
{
|
||||
return $this->currentColumnIndex;
|
||||
}
|
||||
@@ -180,10 +180,10 @@ class RowCellIterator extends CellIterator
|
||||
protected function adjustForExistingOnlyRange(): void
|
||||
{
|
||||
if ($this->onlyExistingCells) {
|
||||
while ((!$this->worksheet->cellExistsByColumnAndRow($this->startColumnIndex, $this->rowIndex)) && ($this->startColumnIndex <= $this->endColumnIndex)) {
|
||||
while ((!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->startColumnIndex) . $this->rowIndex)) && ($this->startColumnIndex <= $this->endColumnIndex)) {
|
||||
++$this->startColumnIndex;
|
||||
}
|
||||
while ((!$this->worksheet->cellExistsByColumnAndRow($this->endColumnIndex, $this->rowIndex)) && ($this->endColumnIndex >= $this->startColumnIndex)) {
|
||||
while ((!$this->cellCollection->has(Coordinate::stringFromColumnIndex($this->endColumnIndex) . $this->rowIndex)) && ($this->endColumnIndex >= $this->startColumnIndex)) {
|
||||
--$this->endColumnIndex;
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Helper\Dimension as CssDimension;
|
||||
|
||||
class RowDimension extends Dimension
|
||||
{
|
||||
/**
|
||||
@@ -30,12 +32,12 @@ class RowDimension extends Dimension
|
||||
/**
|
||||
* Create a new RowDimension.
|
||||
*
|
||||
* @param int $pIndex Numeric row index
|
||||
* @param int $index Numeric row index
|
||||
*/
|
||||
public function __construct($pIndex = 0)
|
||||
public function __construct($index = 0)
|
||||
{
|
||||
// Initialise values
|
||||
$this->rowIndex = $pIndex;
|
||||
$this->rowIndex = $index;
|
||||
|
||||
// set dimension as unformatted by default
|
||||
parent::__construct(null);
|
||||
@@ -43,10 +45,8 @@ class RowDimension extends Dimension
|
||||
|
||||
/**
|
||||
* Get Row Index.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRowIndex()
|
||||
public function getRowIndex(): int
|
||||
{
|
||||
return $this->rowIndex;
|
||||
}
|
||||
@@ -54,47 +54,52 @@ class RowDimension extends Dimension
|
||||
/**
|
||||
* Set Row Index.
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowIndex($pValue)
|
||||
public function setRowIndex(int $index)
|
||||
{
|
||||
$this->rowIndex = $pValue;
|
||||
$this->rowIndex = $index;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Row Height.
|
||||
* By default, this will be in points; but this method also accepts an optional unit of measure
|
||||
* argument, and will convert the value from points to the specified UoM.
|
||||
* A value of -1 tells Excel to display this column in its default height.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getRowHeight()
|
||||
public function getRowHeight(?string $unitOfMeasure = null)
|
||||
{
|
||||
return $this->height;
|
||||
return ($unitOfMeasure === null || $this->height < 0)
|
||||
? $this->height
|
||||
: (new CssDimension($this->height . CssDimension::UOM_POINTS))->toUnit($unitOfMeasure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Row Height.
|
||||
*
|
||||
* @param float $pValue
|
||||
* @param float $height in points. A value of -1 tells Excel to display this column in its default height.
|
||||
* By default, this will be the passed argument value; but this method also accepts an optional unit of measure
|
||||
* argument, and will convert the passed argument value to points from the specified UoM
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowHeight($pValue)
|
||||
public function setRowHeight($height, ?string $unitOfMeasure = null)
|
||||
{
|
||||
$this->height = $pValue;
|
||||
$this->height = ($unitOfMeasure === null || $height < 0)
|
||||
? $height
|
||||
: (new CssDimension("{$height}{$unitOfMeasure}"))->height();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ZeroHeight.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getZeroHeight()
|
||||
public function getZeroHeight(): bool
|
||||
{
|
||||
return $this->zeroHeight;
|
||||
}
|
||||
@@ -102,13 +107,11 @@ class RowDimension extends Dimension
|
||||
/**
|
||||
* Set ZeroHeight.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setZeroHeight($pValue)
|
||||
public function setZeroHeight(bool $zeroHeight)
|
||||
{
|
||||
$this->zeroHeight = $pValue;
|
||||
$this->zeroHeight = $zeroHeight;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use Iterator;
|
||||
use Iterator as NativeIterator;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
class RowIterator implements Iterator
|
||||
/**
|
||||
* @implements NativeIterator<int, Row>
|
||||
*/
|
||||
class RowIterator implements NativeIterator
|
||||
{
|
||||
/**
|
||||
* Worksheet to iterate.
|
||||
@@ -50,14 +53,6 @@ class RowIterator implements Iterator
|
||||
$this->resetStart($startRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->subject = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)Set the start row and the current row pointer.
|
||||
*
|
||||
@@ -65,10 +60,12 @@ class RowIterator implements Iterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startRow = 1)
|
||||
public function resetStart(int $startRow = 1)
|
||||
{
|
||||
if ($startRow > $this->subject->getHighestRow()) {
|
||||
throw new PhpSpreadsheetException("Start row ({$startRow}) is beyond highest row ({$this->subject->getHighestRow()})");
|
||||
throw new PhpSpreadsheetException(
|
||||
"Start row ({$startRow}) is beyond highest row ({$this->subject->getHighestRow()})"
|
||||
);
|
||||
}
|
||||
|
||||
$this->startRow = $startRow;
|
||||
@@ -89,7 +86,7 @@ class RowIterator implements Iterator
|
||||
*/
|
||||
public function resetEnd($endRow = null)
|
||||
{
|
||||
$this->endRow = ($endRow) ? $endRow : $this->subject->getHighestRow();
|
||||
$this->endRow = $endRow ?: $this->subject->getHighestRow();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -101,7 +98,7 @@ class RowIterator implements Iterator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($row = 1)
|
||||
public function seek(int $row = 1)
|
||||
{
|
||||
if (($row < $this->startRow) || ($row > $this->endRow)) {
|
||||
throw new PhpSpreadsheetException("Row $row is out of range ({$this->startRow} - {$this->endRow})");
|
||||
@@ -121,20 +118,16 @@ class RowIterator implements Iterator
|
||||
|
||||
/**
|
||||
* Return the current row in this worksheet.
|
||||
*
|
||||
* @return Row
|
||||
*/
|
||||
public function current()
|
||||
public function current(): Row
|
||||
{
|
||||
return new Row($this->subject, $this->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current iterator key.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function key()
|
||||
public function key(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
@@ -157,10 +150,8 @@ class RowIterator implements Iterator
|
||||
|
||||
/**
|
||||
* Indicate if more rows exist in the worksheet range of rows that we're iterating.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid()
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->position <= $this->endRow && $this->position >= $this->startRow;
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ class SheetView
|
||||
const SHEETVIEW_PAGE_LAYOUT = 'pageLayout';
|
||||
const SHEETVIEW_PAGE_BREAK_PREVIEW = 'pageBreakPreview';
|
||||
|
||||
private static $sheetViewTypes = [
|
||||
private const SHEET_VIEW_TYPES = [
|
||||
self::SHEETVIEW_NORMAL,
|
||||
self::SHEETVIEW_PAGE_LAYOUT,
|
||||
self::SHEETVIEW_PAGE_BREAK_PREVIEW,
|
||||
@@ -22,7 +22,7 @@ class SheetView
|
||||
*
|
||||
* Valid values range from 10 to 400.
|
||||
*
|
||||
* @var int
|
||||
* @var ?int
|
||||
*/
|
||||
private $zoomScale = 100;
|
||||
|
||||
@@ -31,7 +31,7 @@ class SheetView
|
||||
*
|
||||
* Valid values range from 10 to 400.
|
||||
*
|
||||
* @var int
|
||||
* @var ?int
|
||||
*/
|
||||
private $zoomScaleNormal = 100;
|
||||
|
||||
@@ -64,7 +64,7 @@ class SheetView
|
||||
/**
|
||||
* Get ZoomScale.
|
||||
*
|
||||
* @return int
|
||||
* @return ?int
|
||||
*/
|
||||
public function getZoomScale()
|
||||
{
|
||||
@@ -75,16 +75,16 @@ class SheetView
|
||||
* Set ZoomScale.
|
||||
* Valid values range from 10 to 400.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param ?int $zoomScale
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setZoomScale($pValue)
|
||||
public function setZoomScale($zoomScale)
|
||||
{
|
||||
// Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface,
|
||||
// but it is apparently still able to handle any scale >= 1
|
||||
if (($pValue >= 1) || $pValue === null) {
|
||||
$this->zoomScale = $pValue;
|
||||
if ($zoomScale === null || $zoomScale >= 1) {
|
||||
$this->zoomScale = $zoomScale;
|
||||
} else {
|
||||
throw new PhpSpreadsheetException('Scale must be greater than or equal to 1.');
|
||||
}
|
||||
@@ -95,7 +95,7 @@ class SheetView
|
||||
/**
|
||||
* Get ZoomScaleNormal.
|
||||
*
|
||||
* @return int
|
||||
* @return ?int
|
||||
*/
|
||||
public function getZoomScaleNormal()
|
||||
{
|
||||
@@ -106,14 +106,14 @@ class SheetView
|
||||
* Set ZoomScale.
|
||||
* Valid values range from 10 to 400.
|
||||
*
|
||||
* @param int $pValue
|
||||
* @param ?int $zoomScaleNormal
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setZoomScaleNormal($pValue)
|
||||
public function setZoomScaleNormal($zoomScaleNormal)
|
||||
{
|
||||
if (($pValue >= 1) || $pValue === null) {
|
||||
$this->zoomScaleNormal = $pValue;
|
||||
if ($zoomScaleNormal === null || $zoomScaleNormal >= 1) {
|
||||
$this->zoomScaleNormal = $zoomScaleNormal;
|
||||
} else {
|
||||
throw new PhpSpreadsheetException('Scale must be greater than or equal to 1.');
|
||||
}
|
||||
@@ -124,11 +124,11 @@ class SheetView
|
||||
/**
|
||||
* Set ShowZeroes setting.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param bool $showZeros
|
||||
*/
|
||||
public function setShowZeros($pValue): void
|
||||
public function setShowZeros($showZeros): void
|
||||
{
|
||||
$this->showZeros = $pValue;
|
||||
$this->showZeros = $showZeros;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,18 +157,18 @@ class SheetView
|
||||
* 'pageLayout' self::SHEETVIEW_PAGE_LAYOUT
|
||||
* 'pageBreakPreview' self::SHEETVIEW_PAGE_BREAK_PREVIEW
|
||||
*
|
||||
* @param string $pValue
|
||||
* @param ?string $sheetViewType
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setView($pValue)
|
||||
public function setView($sheetViewType)
|
||||
{
|
||||
// MS Excel 2007 allows setting the view to 'normal', 'pageLayout' or 'pageBreakPreview' via the user interface
|
||||
if ($pValue === null) {
|
||||
$pValue = self::SHEETVIEW_NORMAL;
|
||||
if ($sheetViewType === null) {
|
||||
$sheetViewType = self::SHEETVIEW_NORMAL;
|
||||
}
|
||||
if (in_array($pValue, self::$sheetViewTypes)) {
|
||||
$this->sheetviewType = $pValue;
|
||||
if (in_array($sheetViewType, self::SHEET_VIEW_TYPES)) {
|
||||
$this->sheetviewType = $sheetViewType;
|
||||
} else {
|
||||
throw new PhpSpreadsheetException('Invalid sheetview layout type.');
|
||||
}
|
||||
|
585
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php
vendored
Normal file
585
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php
vendored
Normal file
@@ -0,0 +1,585 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;
|
||||
|
||||
class Table
|
||||
{
|
||||
/**
|
||||
* Table Name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Show Header Row.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showHeaderRow = true;
|
||||
|
||||
/**
|
||||
* Show Totals Row.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showTotalsRow = false;
|
||||
|
||||
/**
|
||||
* Table Range.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $range = '';
|
||||
|
||||
/**
|
||||
* Table Worksheet.
|
||||
*
|
||||
* @var null|Worksheet
|
||||
*/
|
||||
private $workSheet;
|
||||
|
||||
/**
|
||||
* Table allow filter.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $allowFilter = true;
|
||||
|
||||
/**
|
||||
* Table Column.
|
||||
*
|
||||
* @var Table\Column[]
|
||||
*/
|
||||
private $columns = [];
|
||||
|
||||
/**
|
||||
* Table Style.
|
||||
*
|
||||
* @var TableStyle
|
||||
*/
|
||||
private $style;
|
||||
|
||||
/**
|
||||
* Table AutoFilter.
|
||||
*
|
||||
* @var AutoFilter
|
||||
*/
|
||||
private $autoFilter;
|
||||
|
||||
/**
|
||||
* Create a new Table.
|
||||
*
|
||||
* @param AddressRange|array<int>|string $range
|
||||
* A simple string containing a Cell range like 'A1:E10' is permitted
|
||||
* or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
|
||||
* or an AddressRange object.
|
||||
* @param string $name (e.g. Table1)
|
||||
*/
|
||||
public function __construct($range = '', string $name = '')
|
||||
{
|
||||
$this->style = new TableStyle();
|
||||
$this->autoFilter = new AutoFilter($range);
|
||||
$this->setRange($range);
|
||||
$this->setName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Table name.
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table name.
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*/
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$name = trim($name);
|
||||
|
||||
if (!empty($name)) {
|
||||
if (strlen($name) === 1 && in_array($name, ['C', 'c', 'R', 'r'])) {
|
||||
throw new PhpSpreadsheetException('The table name is invalid');
|
||||
}
|
||||
if (StringHelper::countCharacters($name) > 255) {
|
||||
throw new PhpSpreadsheetException('The table name cannot be longer than 255 characters');
|
||||
}
|
||||
// Check for A1 or R1C1 cell reference notation
|
||||
if (
|
||||
preg_match(Coordinate::A1_COORDINATE_REGEX, $name) ||
|
||||
preg_match('/^R\[?\-?[0-9]*\]?C\[?\-?[0-9]*\]?$/i', $name)
|
||||
) {
|
||||
throw new PhpSpreadsheetException('The table name can\'t be the same as a cell reference');
|
||||
}
|
||||
if (!preg_match('/^[\p{L}_\\\\]/iu', $name)) {
|
||||
throw new PhpSpreadsheetException('The table name must begin a name with a letter, an underscore character (_), or a backslash (\)');
|
||||
}
|
||||
if (!preg_match('/^[\p{L}_\\\\][\p{L}\p{M}0-9\._]+$/iu', $name)) {
|
||||
throw new PhpSpreadsheetException('The table name contains invalid characters');
|
||||
}
|
||||
|
||||
$this->checkForDuplicateTableNames($name, $this->workSheet);
|
||||
$this->updateStructuredReferences($name);
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PhpSpreadsheetException
|
||||
*/
|
||||
private function checkForDuplicateTableNames(string $name, ?Worksheet $worksheet): void
|
||||
{
|
||||
// Remember that table names are case-insensitive
|
||||
$tableName = StringHelper::strToLower($name);
|
||||
|
||||
if ($worksheet !== null && StringHelper::strToLower($this->name) !== $name) {
|
||||
$spreadsheet = $worksheet->getParent();
|
||||
|
||||
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
|
||||
foreach ($sheet->getTableCollection() as $table) {
|
||||
if (StringHelper::strToLower($table->getName()) === $tableName && $table != $this) {
|
||||
throw new PhpSpreadsheetException("Spreadsheet already contains a table named '{$this->name}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateStructuredReferences(string $name): void
|
||||
{
|
||||
if ($this->workSheet === null || $this->name === null || $this->name === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember that table names are case-insensitive
|
||||
if (StringHelper::strToLower($this->name) !== StringHelper::strToLower($name)) {
|
||||
// We need to check all formula cells that might contain fully-qualified Structured References
|
||||
// that refer to this table, and update those formulae to reference the new table name
|
||||
$spreadsheet = $this->workSheet->getParent();
|
||||
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
|
||||
$this->updateStructuredReferencesInCells($sheet, $name);
|
||||
}
|
||||
$this->updateStructuredReferencesInNamedFormulae($spreadsheet, $name);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateStructuredReferencesInCells(Worksheet $worksheet, string $newName): void
|
||||
{
|
||||
$pattern = '/' . preg_quote($this->name) . '\[/mui';
|
||||
|
||||
foreach ($worksheet->getCoordinates(false) as $coordinate) {
|
||||
$cell = $worksheet->getCell($coordinate);
|
||||
if ($cell->getDataType() === DataType::TYPE_FORMULA) {
|
||||
$formula = $cell->getValue();
|
||||
if (preg_match($pattern, $formula) === 1) {
|
||||
$formula = preg_replace($pattern, "{$newName}[", $formula);
|
||||
$cell->setValueExplicit($formula, DataType::TYPE_FORMULA);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $newName): void
|
||||
{
|
||||
$pattern = '/' . preg_quote($this->name) . '\[/mui';
|
||||
|
||||
foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
|
||||
$formula = $namedFormula->getValue();
|
||||
if (preg_match($pattern, $formula) === 1) {
|
||||
$formula = preg_replace($pattern, "{$newName}[", $formula);
|
||||
$namedFormula->setValue($formula); // @phpstan-ignore-line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Header Row.
|
||||
*/
|
||||
public function getShowHeaderRow(): bool
|
||||
{
|
||||
return $this->showHeaderRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Header Row.
|
||||
*/
|
||||
public function setShowHeaderRow(bool $showHeaderRow): self
|
||||
{
|
||||
$this->showHeaderRow = $showHeaderRow;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Totals Row.
|
||||
*/
|
||||
public function getShowTotalsRow(): bool
|
||||
{
|
||||
return $this->showTotalsRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Totals Row.
|
||||
*/
|
||||
public function setShowTotalsRow(bool $showTotalsRow): self
|
||||
{
|
||||
$this->showTotalsRow = $showTotalsRow;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allow filter.
|
||||
* If false, autofiltering is disabled for the table, if true it is enabled.
|
||||
*/
|
||||
public function getAllowFilter(): bool
|
||||
{
|
||||
return $this->allowFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Autofiltering.
|
||||
* Disabling autofiltering has the same effect as hiding the filter button on all the columns in the table.
|
||||
*/
|
||||
public function setAllowFilter(bool $allowFilter): self
|
||||
{
|
||||
$this->allowFilter = $allowFilter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Table Range.
|
||||
*/
|
||||
public function getRange(): string
|
||||
{
|
||||
return $this->range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table Cell Range.
|
||||
*
|
||||
* @param AddressRange|array<int>|string $range
|
||||
* A simple string containing a Cell range like 'A1:E10' is permitted
|
||||
* or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
|
||||
* or an AddressRange object.
|
||||
*/
|
||||
public function setRange($range = ''): self
|
||||
{
|
||||
// extract coordinate
|
||||
if ($range !== '') {
|
||||
[, $range] = Worksheet::extractSheetTitle(Validations::validateCellRange($range), true);
|
||||
}
|
||||
if (empty($range)) {
|
||||
// Discard all column rules
|
||||
$this->columns = [];
|
||||
$this->range = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (strpos($range, ':') === false) {
|
||||
throw new PhpSpreadsheetException('Table must be set on a range of cells.');
|
||||
}
|
||||
|
||||
[$width, $height] = Coordinate::rangeDimension($range);
|
||||
if ($width < 1 || $height < 2) {
|
||||
throw new PhpSpreadsheetException('The table range must be at least 1 column and 2 rows');
|
||||
}
|
||||
|
||||
$this->range = $range;
|
||||
$this->autoFilter->setRange($range);
|
||||
|
||||
// Discard any column rules that are no longer valid within this range
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
foreach ($this->columns as $key => $value) {
|
||||
$colIndex = Coordinate::columnIndexFromString($key);
|
||||
if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) {
|
||||
unset($this->columns[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table Cell Range to max row.
|
||||
*/
|
||||
public function setRangeToMaxRow(): self
|
||||
{
|
||||
if ($this->workSheet !== null) {
|
||||
$thisrange = $this->range;
|
||||
$range = (string) preg_replace('/\\d+$/', (string) $this->workSheet->getHighestRow(), $thisrange);
|
||||
if ($range !== $thisrange) {
|
||||
$this->setRange($range);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Table's Worksheet.
|
||||
*/
|
||||
public function getWorksheet(): ?Worksheet
|
||||
{
|
||||
return $this->workSheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table's Worksheet.
|
||||
*/
|
||||
public function setWorksheet(?Worksheet $worksheet = null): self
|
||||
{
|
||||
if ($this->name !== '' && $worksheet !== null) {
|
||||
$spreadsheet = $worksheet->getParent();
|
||||
$tableName = StringHelper::strToUpper($this->name);
|
||||
|
||||
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
|
||||
foreach ($sheet->getTableCollection() as $table) {
|
||||
if (StringHelper::strToUpper($table->getName()) === $tableName) {
|
||||
throw new PhpSpreadsheetException("Workbook already contains a table named '{$this->name}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->workSheet = $worksheet;
|
||||
$this->autoFilter->setParent($worksheet);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Table Columns.
|
||||
*
|
||||
* @return Table\Column[]
|
||||
*/
|
||||
public function getColumns(): array
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the specified column is in the Table range.
|
||||
*
|
||||
* @param string $column Column name (e.g. A)
|
||||
*
|
||||
* @return int The column offset within the table range
|
||||
*/
|
||||
public function isColumnInRange(string $column): int
|
||||
{
|
||||
if (empty($this->range)) {
|
||||
throw new PhpSpreadsheetException('No table range is defined.');
|
||||
}
|
||||
|
||||
$columnIndex = Coordinate::columnIndexFromString($column);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) {
|
||||
throw new PhpSpreadsheetException('Column is outside of current table range.');
|
||||
}
|
||||
|
||||
return $columnIndex - $rangeStart[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specified Table Column Offset within the defined Table range.
|
||||
*
|
||||
* @param string $column Column name (e.g. A)
|
||||
*
|
||||
* @return int The offset of the specified column within the table range
|
||||
*/
|
||||
public function getColumnOffset($column): int
|
||||
{
|
||||
return $this->isColumnInRange($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specified Table Column.
|
||||
*
|
||||
* @param string $column Column name (e.g. A)
|
||||
*/
|
||||
public function getColumn($column): Table\Column
|
||||
{
|
||||
$this->isColumnInRange($column);
|
||||
|
||||
if (!isset($this->columns[$column])) {
|
||||
$this->columns[$column] = new Table\Column($column, $this);
|
||||
}
|
||||
|
||||
return $this->columns[$column];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specified Table Column by it's offset.
|
||||
*
|
||||
* @param int $columnOffset Column offset within range (starting from 0)
|
||||
*/
|
||||
public function getColumnByOffset($columnOffset): Table\Column
|
||||
{
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
$pColumn = Coordinate::stringFromColumnIndex($rangeStart[0] + $columnOffset);
|
||||
|
||||
return $this->getColumn($pColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table.
|
||||
*
|
||||
* @param string|Table\Column $columnObjectOrString
|
||||
* A simple string containing a Column ID like 'A' is permitted
|
||||
*/
|
||||
public function setColumn($columnObjectOrString): self
|
||||
{
|
||||
if ((is_string($columnObjectOrString)) && (!empty($columnObjectOrString))) {
|
||||
$column = $columnObjectOrString;
|
||||
} elseif (is_object($columnObjectOrString) && ($columnObjectOrString instanceof Table\Column)) {
|
||||
$column = $columnObjectOrString->getColumnIndex();
|
||||
} else {
|
||||
throw new PhpSpreadsheetException('Column is not within the table range.');
|
||||
}
|
||||
$this->isColumnInRange($column);
|
||||
|
||||
if (is_string($columnObjectOrString)) {
|
||||
$this->columns[$columnObjectOrString] = new Table\Column($columnObjectOrString, $this);
|
||||
} else {
|
||||
$columnObjectOrString->setTable($this);
|
||||
$this->columns[$column] = $columnObjectOrString;
|
||||
}
|
||||
ksort($this->columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a specified Table Column.
|
||||
*
|
||||
* @param string $column Column name (e.g. A)
|
||||
*/
|
||||
public function clearColumn($column): self
|
||||
{
|
||||
$this->isColumnInRange($column);
|
||||
|
||||
if (isset($this->columns[$column])) {
|
||||
unset($this->columns[$column]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift an Table Column Rule to a different column.
|
||||
*
|
||||
* Note: This method bypasses validation of the destination column to ensure it is within this Table range.
|
||||
* Nor does it verify whether any column rule already exists at $toColumn, but will simply override any existing value.
|
||||
* Use with caution.
|
||||
*
|
||||
* @param string $fromColumn Column name (e.g. A)
|
||||
* @param string $toColumn Column name (e.g. B)
|
||||
*/
|
||||
public function shiftColumn($fromColumn, $toColumn): self
|
||||
{
|
||||
$fromColumn = strtoupper($fromColumn);
|
||||
$toColumn = strtoupper($toColumn);
|
||||
|
||||
if (($fromColumn !== null) && (isset($this->columns[$fromColumn])) && ($toColumn !== null)) {
|
||||
$this->columns[$fromColumn]->setTable();
|
||||
$this->columns[$fromColumn]->setColumnIndex($toColumn);
|
||||
$this->columns[$toColumn] = $this->columns[$fromColumn];
|
||||
$this->columns[$toColumn]->setTable($this);
|
||||
unset($this->columns[$fromColumn]);
|
||||
|
||||
ksort($this->columns);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table Style.
|
||||
*/
|
||||
public function getStyle(): Table\TableStyle
|
||||
{
|
||||
return $this->style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set table Style.
|
||||
*/
|
||||
public function setStyle(TableStyle $style): self
|
||||
{
|
||||
$this->style = $style;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AutoFilter.
|
||||
*/
|
||||
public function getAutoFilter(): AutoFilter
|
||||
{
|
||||
return $this->autoFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AutoFilter.
|
||||
*/
|
||||
public function setAutoFilter(AutoFilter $autoFilter): self
|
||||
{
|
||||
$this->autoFilter = $autoFilter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement PHP __clone to create a deep clone, not just a shallow copy.
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
foreach ($vars as $key => $value) {
|
||||
if (is_object($value)) {
|
||||
if ($key === 'workSheet') {
|
||||
// Detach from worksheet
|
||||
$this->{$key} = null;
|
||||
} else {
|
||||
$this->{$key} = clone $value;
|
||||
}
|
||||
} elseif ((is_array($value)) && ($key === 'columns')) {
|
||||
// The columns array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\Table objects
|
||||
$this->{$key} = [];
|
||||
foreach ($value as $k => $v) {
|
||||
$this->{$key}[$k] = clone $v;
|
||||
// attach the new cloned Column to this new cloned Table object
|
||||
$this->{$key}[$k]->setTable($this);
|
||||
}
|
||||
} else {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* toString method replicates previous behavior by returning the range if object is
|
||||
* referenced as a property of its worksheet.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->range;
|
||||
}
|
||||
}
|
254
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php
vendored
Normal file
254
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet\Table;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class Column
|
||||
{
|
||||
/**
|
||||
* Table Column Index.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $columnIndex = '';
|
||||
|
||||
/**
|
||||
* Show Filter Button.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showFilterButton = true;
|
||||
|
||||
/**
|
||||
* Total Row Label.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $totalsRowLabel;
|
||||
|
||||
/**
|
||||
* Total Row Function.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $totalsRowFunction;
|
||||
|
||||
/**
|
||||
* Total Row Formula.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $totalsRowFormula;
|
||||
|
||||
/**
|
||||
* Column Formula.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $columnFormula;
|
||||
|
||||
/**
|
||||
* Table.
|
||||
*
|
||||
* @var null|Table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* Create a new Column.
|
||||
*
|
||||
* @param string $column Column (e.g. A)
|
||||
* @param Table $table Table for this column
|
||||
*/
|
||||
public function __construct($column, ?Table $table = null)
|
||||
{
|
||||
$this->columnIndex = $column;
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Table column index as string eg: 'A'.
|
||||
*/
|
||||
public function getColumnIndex(): string
|
||||
{
|
||||
return $this->columnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Table column index as string eg: 'A'.
|
||||
*
|
||||
* @param string $column Column (e.g. A)
|
||||
*/
|
||||
public function setColumnIndex($column): self
|
||||
{
|
||||
// Uppercase coordinate
|
||||
$column = strtoupper($column);
|
||||
if ($this->table !== null) {
|
||||
$this->table->isColumnInRange($column);
|
||||
}
|
||||
|
||||
$this->columnIndex = $column;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Filter Button.
|
||||
*/
|
||||
public function getShowFilterButton(): bool
|
||||
{
|
||||
return $this->showFilterButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Filter Button.
|
||||
*/
|
||||
public function setShowFilterButton(bool $showFilterButton): self
|
||||
{
|
||||
$this->showFilterButton = $showFilterButton;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total Row Label.
|
||||
*/
|
||||
public function getTotalsRowLabel(): ?string
|
||||
{
|
||||
return $this->totalsRowLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set total Row Label.
|
||||
*/
|
||||
public function setTotalsRowLabel(string $totalsRowLabel): self
|
||||
{
|
||||
$this->totalsRowLabel = $totalsRowLabel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total Row Function.
|
||||
*/
|
||||
public function getTotalsRowFunction(): ?string
|
||||
{
|
||||
return $this->totalsRowFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set total Row Function.
|
||||
*/
|
||||
public function setTotalsRowFunction(string $totalsRowFunction): self
|
||||
{
|
||||
$this->totalsRowFunction = $totalsRowFunction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total Row Formula.
|
||||
*/
|
||||
public function getTotalsRowFormula(): ?string
|
||||
{
|
||||
return $this->totalsRowFormula;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set total Row Formula.
|
||||
*/
|
||||
public function setTotalsRowFormula(string $totalsRowFormula): self
|
||||
{
|
||||
$this->totalsRowFormula = $totalsRowFormula;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column Formula.
|
||||
*/
|
||||
public function getColumnFormula(): ?string
|
||||
{
|
||||
return $this->columnFormula;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column Formula.
|
||||
*/
|
||||
public function setColumnFormula(string $columnFormula): self
|
||||
{
|
||||
$this->columnFormula = $columnFormula;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this Column's Table.
|
||||
*/
|
||||
public function getTable(): ?Table
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Column's Table.
|
||||
*/
|
||||
public function setTable(?Table $table = null): self
|
||||
{
|
||||
$this->table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function updateStructuredReferences(?Worksheet $workSheet, ?string $oldTitle, string $newTitle): void
|
||||
{
|
||||
if ($workSheet === null || $oldTitle === null || $oldTitle === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember that table headings are case-insensitive
|
||||
if (StringHelper::strToLower($oldTitle) !== StringHelper::strToLower($newTitle)) {
|
||||
// We need to check all formula cells that might contain Structured References that refer
|
||||
// to this column, and update those formulae to reference the new column text
|
||||
$spreadsheet = $workSheet->getParent();
|
||||
foreach ($spreadsheet->getWorksheetIterator() as $sheet) {
|
||||
self::updateStructuredReferencesInCells($sheet, $oldTitle, $newTitle);
|
||||
}
|
||||
self::updateStructuredReferencesInNamedFormulae($spreadsheet, $oldTitle, $newTitle);
|
||||
}
|
||||
}
|
||||
|
||||
private static function updateStructuredReferencesInCells(Worksheet $worksheet, string $oldTitle, string $newTitle): void
|
||||
{
|
||||
$pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui';
|
||||
|
||||
foreach ($worksheet->getCoordinates(false) as $coordinate) {
|
||||
$cell = $worksheet->getCell($coordinate);
|
||||
if ($cell->getDataType() === DataType::TYPE_FORMULA) {
|
||||
$formula = $cell->getValue();
|
||||
if (preg_match($pattern, $formula) === 1) {
|
||||
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula);
|
||||
$cell->setValueExplicit($formula, DataType::TYPE_FORMULA);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function updateStructuredReferencesInNamedFormulae(Spreadsheet $spreadsheet, string $oldTitle, string $newTitle): void
|
||||
{
|
||||
$pattern = '/\[(@?)' . preg_quote($oldTitle) . '\]/mui';
|
||||
|
||||
foreach ($spreadsheet->getNamedFormulae() as $namedFormula) {
|
||||
$formula = $namedFormula->getValue();
|
||||
if (preg_match($pattern, $formula) === 1) {
|
||||
$formula = preg_replace($pattern, "[$1{$newTitle}]", $formula);
|
||||
$namedFormula->setValue($formula); // @phpstan-ignore-line
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
230
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php
vendored
Normal file
230
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet\Table;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
|
||||
|
||||
class TableStyle
|
||||
{
|
||||
const TABLE_STYLE_NONE = '';
|
||||
const TABLE_STYLE_LIGHT1 = 'TableStyleLight1';
|
||||
const TABLE_STYLE_LIGHT2 = 'TableStyleLight2';
|
||||
const TABLE_STYLE_LIGHT3 = 'TableStyleLight3';
|
||||
const TABLE_STYLE_LIGHT4 = 'TableStyleLight4';
|
||||
const TABLE_STYLE_LIGHT5 = 'TableStyleLight5';
|
||||
const TABLE_STYLE_LIGHT6 = 'TableStyleLight6';
|
||||
const TABLE_STYLE_LIGHT7 = 'TableStyleLight7';
|
||||
const TABLE_STYLE_LIGHT8 = 'TableStyleLight8';
|
||||
const TABLE_STYLE_LIGHT9 = 'TableStyleLight9';
|
||||
const TABLE_STYLE_LIGHT10 = 'TableStyleLight10';
|
||||
const TABLE_STYLE_LIGHT11 = 'TableStyleLight11';
|
||||
const TABLE_STYLE_LIGHT12 = 'TableStyleLight12';
|
||||
const TABLE_STYLE_LIGHT13 = 'TableStyleLight13';
|
||||
const TABLE_STYLE_LIGHT14 = 'TableStyleLight14';
|
||||
const TABLE_STYLE_LIGHT15 = 'TableStyleLight15';
|
||||
const TABLE_STYLE_LIGHT16 = 'TableStyleLight16';
|
||||
const TABLE_STYLE_LIGHT17 = 'TableStyleLight17';
|
||||
const TABLE_STYLE_LIGHT18 = 'TableStyleLight18';
|
||||
const TABLE_STYLE_LIGHT19 = 'TableStyleLight19';
|
||||
const TABLE_STYLE_LIGHT20 = 'TableStyleLight20';
|
||||
const TABLE_STYLE_LIGHT21 = 'TableStyleLight21';
|
||||
const TABLE_STYLE_MEDIUM1 = 'TableStyleMedium1';
|
||||
const TABLE_STYLE_MEDIUM2 = 'TableStyleMedium2';
|
||||
const TABLE_STYLE_MEDIUM3 = 'TableStyleMedium3';
|
||||
const TABLE_STYLE_MEDIUM4 = 'TableStyleMedium4';
|
||||
const TABLE_STYLE_MEDIUM5 = 'TableStyleMedium5';
|
||||
const TABLE_STYLE_MEDIUM6 = 'TableStyleMedium6';
|
||||
const TABLE_STYLE_MEDIUM7 = 'TableStyleMedium7';
|
||||
const TABLE_STYLE_MEDIUM8 = 'TableStyleMedium8';
|
||||
const TABLE_STYLE_MEDIUM9 = 'TableStyleMedium9';
|
||||
const TABLE_STYLE_MEDIUM10 = 'TableStyleMedium10';
|
||||
const TABLE_STYLE_MEDIUM11 = 'TableStyleMedium11';
|
||||
const TABLE_STYLE_MEDIUM12 = 'TableStyleMedium12';
|
||||
const TABLE_STYLE_MEDIUM13 = 'TableStyleMedium13';
|
||||
const TABLE_STYLE_MEDIUM14 = 'TableStyleMedium14';
|
||||
const TABLE_STYLE_MEDIUM15 = 'TableStyleMedium15';
|
||||
const TABLE_STYLE_MEDIUM16 = 'TableStyleMedium16';
|
||||
const TABLE_STYLE_MEDIUM17 = 'TableStyleMedium17';
|
||||
const TABLE_STYLE_MEDIUM18 = 'TableStyleMedium18';
|
||||
const TABLE_STYLE_MEDIUM19 = 'TableStyleMedium19';
|
||||
const TABLE_STYLE_MEDIUM20 = 'TableStyleMedium20';
|
||||
const TABLE_STYLE_MEDIUM21 = 'TableStyleMedium21';
|
||||
const TABLE_STYLE_MEDIUM22 = 'TableStyleMedium22';
|
||||
const TABLE_STYLE_MEDIUM23 = 'TableStyleMedium23';
|
||||
const TABLE_STYLE_MEDIUM24 = 'TableStyleMedium24';
|
||||
const TABLE_STYLE_MEDIUM25 = 'TableStyleMedium25';
|
||||
const TABLE_STYLE_MEDIUM26 = 'TableStyleMedium26';
|
||||
const TABLE_STYLE_MEDIUM27 = 'TableStyleMedium27';
|
||||
const TABLE_STYLE_MEDIUM28 = 'TableStyleMedium28';
|
||||
const TABLE_STYLE_DARK1 = 'TableStyleDark1';
|
||||
const TABLE_STYLE_DARK2 = 'TableStyleDark2';
|
||||
const TABLE_STYLE_DARK3 = 'TableStyleDark3';
|
||||
const TABLE_STYLE_DARK4 = 'TableStyleDark4';
|
||||
const TABLE_STYLE_DARK5 = 'TableStyleDark5';
|
||||
const TABLE_STYLE_DARK6 = 'TableStyleDark6';
|
||||
const TABLE_STYLE_DARK7 = 'TableStyleDark7';
|
||||
const TABLE_STYLE_DARK8 = 'TableStyleDark8';
|
||||
const TABLE_STYLE_DARK9 = 'TableStyleDark9';
|
||||
const TABLE_STYLE_DARK10 = 'TableStyleDark10';
|
||||
const TABLE_STYLE_DARK11 = 'TableStyleDark11';
|
||||
|
||||
/**
|
||||
* Theme.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $theme;
|
||||
|
||||
/**
|
||||
* Show First Column.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showFirstColumn = false;
|
||||
|
||||
/**
|
||||
* Show Last Column.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showLastColumn = false;
|
||||
|
||||
/**
|
||||
* Show Row Stripes.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showRowStripes = false;
|
||||
|
||||
/**
|
||||
* Show Column Stripes.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showColumnStripes = false;
|
||||
|
||||
/**
|
||||
* Table.
|
||||
*
|
||||
* @var null|Table
|
||||
*/
|
||||
private $table;
|
||||
|
||||
/**
|
||||
* Create a new Table Style.
|
||||
*
|
||||
* @param string $theme (e.g. TableStyle::TABLE_STYLE_MEDIUM2)
|
||||
*/
|
||||
public function __construct(string $theme = self::TABLE_STYLE_MEDIUM2)
|
||||
{
|
||||
$this->theme = $theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get theme.
|
||||
*/
|
||||
public function getTheme(): string
|
||||
{
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set theme.
|
||||
*/
|
||||
public function setTheme(string $theme): self
|
||||
{
|
||||
$this->theme = $theme;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show First Column.
|
||||
*/
|
||||
public function getShowFirstColumn(): bool
|
||||
{
|
||||
return $this->showFirstColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show First Column.
|
||||
*/
|
||||
public function setShowFirstColumn(bool $showFirstColumn): self
|
||||
{
|
||||
$this->showFirstColumn = $showFirstColumn;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Last Column.
|
||||
*/
|
||||
public function getShowLastColumn(): bool
|
||||
{
|
||||
return $this->showLastColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Last Column.
|
||||
*/
|
||||
public function setShowLastColumn(bool $showLastColumn): self
|
||||
{
|
||||
$this->showLastColumn = $showLastColumn;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Row Stripes.
|
||||
*/
|
||||
public function getShowRowStripes(): bool
|
||||
{
|
||||
return $this->showRowStripes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Row Stripes.
|
||||
*/
|
||||
public function setShowRowStripes(bool $showRowStripes): self
|
||||
{
|
||||
$this->showRowStripes = $showRowStripes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get show Column Stripes.
|
||||
*/
|
||||
public function getShowColumnStripes(): bool
|
||||
{
|
||||
return $this->showColumnStripes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show Column Stripes.
|
||||
*/
|
||||
public function setShowColumnStripes(bool $showColumnStripes): self
|
||||
{
|
||||
$this->showColumnStripes = $showColumnStripes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this Style's Table.
|
||||
*/
|
||||
public function getTable(): ?Table
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Style's Table.
|
||||
*/
|
||||
public function setTable(?Table $table = null): self
|
||||
{
|
||||
$this->table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
115
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php
vendored
Normal file
115
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\CellRange;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
|
||||
|
||||
class Validations
|
||||
{
|
||||
/**
|
||||
* Validate a cell address.
|
||||
*
|
||||
* @param null|array<int>|CellAddress|string $cellAddress Coordinate of the cell as a string, eg: 'C5';
|
||||
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
|
||||
*/
|
||||
public static function validateCellAddress($cellAddress): string
|
||||
{
|
||||
if (is_string($cellAddress)) {
|
||||
[$worksheet, $address] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
// if (!empty($worksheet) && $worksheet !== $this->getTitle()) {
|
||||
// throw new Exception('Reference is not for this worksheet');
|
||||
// }
|
||||
|
||||
return empty($worksheet) ? strtoupper("$address") : $worksheet . '!' . strtoupper("$address");
|
||||
}
|
||||
|
||||
if (is_array($cellAddress)) {
|
||||
$cellAddress = CellAddress::fromColumnRowArray($cellAddress);
|
||||
}
|
||||
|
||||
return (string) $cellAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a cell address or cell range.
|
||||
*
|
||||
* @param AddressRange|array<int>|CellAddress|int|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12';
|
||||
* or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]),
|
||||
* or as a CellAddress or AddressRange object.
|
||||
*/
|
||||
public static function validateCellOrCellRange($cellRange): string
|
||||
{
|
||||
if (is_string($cellRange) || is_numeric($cellRange)) {
|
||||
// Convert a single column reference like 'A' to 'A:A',
|
||||
// a single row reference like '1' to '1:1'
|
||||
$cellRange = (string) preg_replace('/^([A-Z]+|\d+)$/', '${1}:${1}', (string) $cellRange);
|
||||
} elseif (is_object($cellRange) && $cellRange instanceof CellAddress) {
|
||||
$cellRange = new CellRange($cellRange, $cellRange);
|
||||
}
|
||||
|
||||
return self::validateCellRange($cellRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a cell range.
|
||||
*
|
||||
* @param AddressRange|array<int>|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12';
|
||||
* or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]),
|
||||
* or as an AddressRange object.
|
||||
*/
|
||||
public static function validateCellRange($cellRange): string
|
||||
{
|
||||
if (is_string($cellRange)) {
|
||||
[$worksheet, $addressRange] = Worksheet::extractSheetTitle($cellRange, true);
|
||||
|
||||
// Convert Column ranges like 'A:C' to 'A1:C1048576'
|
||||
// or Row ranges like '1:3' to 'A1:XFD3'
|
||||
$addressRange = (string) preg_replace(
|
||||
['/^([A-Z]+):([A-Z]+)$/i', '/^(\\d+):(\\d+)$/'],
|
||||
['${1}1:${2}1048576', 'A${1}:XFD${2}'],
|
||||
$addressRange
|
||||
);
|
||||
|
||||
return empty($worksheet) ? strtoupper($addressRange) : $worksheet . '!' . strtoupper($addressRange);
|
||||
}
|
||||
|
||||
if (is_array($cellRange)) {
|
||||
switch (count($cellRange)) {
|
||||
case 2:
|
||||
$from = [$cellRange[0], $cellRange[1]];
|
||||
$to = [$cellRange[0], $cellRange[1]];
|
||||
|
||||
break;
|
||||
case 4:
|
||||
$from = [$cellRange[0], $cellRange[1]];
|
||||
$to = [$cellRange[2], $cellRange[3]];
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new SpreadsheetException('CellRange array length must be 2 or 4');
|
||||
}
|
||||
$cellRange = new CellRange(CellAddress::fromColumnRowArray($from), CellAddress::fromColumnRowArray($to));
|
||||
}
|
||||
|
||||
return (string) $cellRange;
|
||||
}
|
||||
|
||||
public static function definedNameToCoordinate(string $coordinate, Worksheet $worksheet): string
|
||||
{
|
||||
// Uppercase coordinate
|
||||
$coordinate = strtoupper($coordinate);
|
||||
// Eliminate leading equal sign
|
||||
$testCoordinate = (string) preg_replace('/^=/', '', $coordinate);
|
||||
$defined = $worksheet->getParent()->getDefinedName($testCoordinate, $worksheet);
|
||||
if ($defined !== null) {
|
||||
if ($defined->getWorksheet() === $worksheet && !$defined->isFormula()) {
|
||||
$coordinate = (string) preg_replace('/^=/', '', $defined->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return $coordinate;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user