Skip to content

Commit

Permalink
Merge branch 'master' into pr1449
Browse files Browse the repository at this point in the history
  • Loading branch information
oleibman authored Oct 10, 2024
2 parents a921d24 + 39fc513 commit d881cf8
Show file tree
Hide file tree
Showing 57 changed files with 908 additions and 141 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Xlsx Writer Duplicate ContentTypes Entry for Background Image. [Issue #4179](https://github.com/PHPOffice/PhpSpreadsheet/issues/4179) [PR #4180](https://github.com/PHPOffice/PhpSpreadsheet/pull/4180)
- Check strictNullComparison outside of loops. [PR #3347](https://github.com/PHPOffice/PhpSpreadsheet/pull/3347)
- SUMIFS Does Not Require xlfn. [Issue #4182](https://github.com/PHPOffice/PhpSpreadsheet/issues/4182) [PR #4186](https://github.com/PHPOffice/PhpSpreadsheet/pull/4186)
- Image Transparency/Opacity with Html Reader Changes. [Discussion #4117](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4117) [PR #4142](https://github.com/PHPOffice/PhpSpreadsheet/pull/4142)
- Option to Write Hyperlink Rather Than Label to Csv. [Issue #1412](https://github.com/PHPOffice/PhpSpreadsheet/issues/1412) [PR #4151](https://github.com/PHPOffice/PhpSpreadsheet/pull/4151)
- Invalid Html Due to Cached Filesize. [Issue #1107](https://github.com/PHPOffice/PhpSpreadsheet/issues/1107) [PR #4184](https://github.com/PHPOffice/PhpSpreadsheet/pull/4184)
- Add Dynamic valueBinder Property to Spreadsheet and Readers. [Issue #1395](https://github.com/PHPOffice/PhpSpreadsheet/issues/1395) [PR #4185](https://github.com/PHPOffice/PhpSpreadsheet/pull/4185)

## 2024-09-29 - 3.3.0 (no 3.0.\*, 3.1.\*, 3.2.\*)

Expand Down
10 changes: 5 additions & 5 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions docs/topics/Behind the Mask.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ If you wish to emulate the MS Excel behaviour, and automatically convert string

You can do this by changing the Value Binder, which will then apply every time you set a Cell value.
```php
// Old method using static property
Cell::setValueBinder(new AdvancedValueBinder());
// Preferred method using dynamic property since 3.4.0
$spreadsheet->setValueBinder(new AdvancedValueBinder());

// Set Cell C21 using a formatted string value
$worksheet->getCell('C20')->setValue('€ -12345.6789');
Expand Down
3 changes: 3 additions & 0 deletions docs/topics/The Dating Game.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,10 @@ $spreadsheet = new Spreadsheet();
$worksheet = $spreadsheet->getActiveSheet();
// Use the Advanced Value Binder so that our string date/time values will be automatically converted
// to Excel serialized date/timestamps
// Old method using static property
Cell::setValueBinder(new AdvancedValueBinder());
// Preferred method using dynamic property since 3.4.0
$spreadsheet->setValueBinder(new AdvancedValueBinder());

// Write our data to the worksheet
$worksheet->fromArray($projectHeading);
Expand Down
17 changes: 12 additions & 5 deletions docs/topics/accessing-cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,15 +518,15 @@ style information. The following example demonstrates how to set the
value binder in PhpSpreadsheet:

```php
/** PhpSpreadsheet */
require_once 'src/Boostrap.php';

// Set value binder
// Older method using static property
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

// Create new Spreadsheet object
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();

// Preferred method using dynamic property since 3.4.0
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

// ...
// Add some data, resembling some different data types
$spreadsheet->getActiveSheet()->setCellValue('A4', 'Percentage value:');
Expand Down Expand Up @@ -555,13 +555,20 @@ $stringValueBinder->setNumericConversion(false)
->setBooleanConversion(false)
->setNullConversion(false)
->setFormulaConversion(false);
// Older method using static property
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( $stringValueBinder );
// Preferred method using dynamic property since 3.4.0
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$spreadsheet->setValueBinder( $stringValueBinder );
```

You can override the current binder when setting individual cell values by specifying a different Binder to use in the Cell's `setValue()` or the Worksheet's `setCellValue()` methods.
```php
$spreadsheet = new Spreadsheet();
// Old method using static property
Cell::setValueBinder(new AdvancedValueBinder());
// Preferred method using dynamic property since 3.4.0
$spreadsheet->setValueBinder(new AdvancedValueBinder());

$value = '12.5%';

Expand Down
12 changes: 8 additions & 4 deletions docs/topics/reading-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -755,14 +755,18 @@ So using a Value Binder allows a great deal more flexibility in the
loader logic when reading unformatted text files.

```php
/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

$inputFileType = 'Csv';
$inputFileName = './sampleData/example1.tsv';

$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);
$reader->setDelimiter("\t");

/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/
// Old method using static property
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
// Preferred method using dynamic property since 3.4.0
$reader::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

$spreadsheet = $reader->load($inputFileName);
```

Expand All @@ -774,7 +778,7 @@ Loading using a Value Binder applies to:
Reader | Y/N |Reader | Y/N |Reader | Y/N
----------|:---:|--------|:---:|--------------|:---:
Xlsx | NO | Xls | NO | Xml | NO
Ods | NO | SYLK | NO | Gnumeric | NO
Ods | NO | SYLK | YES | Gnumeric | NO
CSV | YES | HTML | YES

Note that you can also use the Binder to determine how PhpSpreadsheet identified datatypes for values when you set a cell value without explicitly setting a datatype.
Expand Down
6 changes: 6 additions & 0 deletions docs/topics/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,10 @@ method that suits you the best. Here are some examples:

```php
// MySQL-like timestamp '2008-12-31' or date string
// Old method using static property
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
// Preferred method using dynamic property since 3.4.0
$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

$spreadsheet->getActiveSheet()
->setCellValue('D1', '2008-12-31');
Expand Down Expand Up @@ -599,7 +602,10 @@ when it sees a newline character in a string that you are inserting in a
cell. Just like Microsoft Office Excel. Try this:

```php
// Old method using static property
\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );
// Preferred method using dynamic property since 3.4.0
$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() );

$spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld");
```
Expand Down
69 changes: 69 additions & 0 deletions samples/Basic4/53_ImageOpacity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

require __DIR__ . '/../Header.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

//var_dump(realpath(__DIR__ . '/../images/blue_square.png'));
//exit();

$path = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'images/blue_square.png';
$spreadsheet = new Spreadsheet();
$spreadsheet->getProperties()->setTitle('53_ImageOpacity');

$helper->log('Add image to spreadsheet 6 times with different opacities');
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('Squares different opacities');
$sheet->setShowGridLines(false);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity not specified');
$drawing->setPath($path);
$drawing->setCoordinates('A1');
$drawing->setCoordinates2('B5');
$drawing->setWorksheet($sheet);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity 80%');
$drawing->setPath($path);
$drawing->setCoordinates('C1');
$drawing->setCoordinates2('D5');
$drawing->setOpacity(80000);
$drawing->setWorksheet($sheet);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity 60%');
$drawing->setPath($path);
$drawing->setCoordinates('E1');
$drawing->setCoordinates2('F5');
$drawing->setOpacity(60000);
$drawing->setWorksheet($sheet);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity 40%');
$drawing->setPath($path);
$drawing->setCoordinates('A8');
$drawing->setCoordinates2('B12');
$drawing->setOpacity(40000);
$drawing->setWorksheet($sheet);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity 20%');
$drawing->setPath($path);
$drawing->setCoordinates('C8');
$drawing->setCoordinates2('D12');
$drawing->setOpacity(20000);
$drawing->setWorksheet($sheet);

$drawing = new Drawing();
$drawing->setName('Blue Square opacity 0%');
$drawing->setPath($path);
$drawing->setCoordinates('E8');
$drawing->setCoordinates2('F12');
$drawing->setOpacity(0);
$drawing->setWorksheet($sheet);

// Save
$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html', 'Dompdf', 'Mpdf']);
$spreadsheet->disconnectWorksheets();
Binary file added samples/images/blue_square.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified samples/templates/27template.xlsx
Binary file not shown.
27 changes: 20 additions & 7 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4160,8 +4160,10 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
}
}
} elseif ($expectedArgumentCount != '*') {
preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch);
switch ($argMatch[2] ?? '') {
if (1 !== preg_match('/(\d*)([-+,])(\d*)/', $expectedArgumentCount, $argMatch)) {
$argMatch = ['', '', '', ''];
}
switch ($argMatch[2]) {
case '+':
if ($argumentCount < $argMatch[1]) {
$argumentCountError = true;
Expand Down Expand Up @@ -4234,7 +4236,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
// do we now have a function/variable/number?
$expectingOperator = true;
$expectingOperand = false;
$val = $match[1];
$val = $match[1] ?? '';
$length = strlen($val);

if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/miu', $val, $matches)) {
Expand Down Expand Up @@ -4290,7 +4292,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
$rangeStartCellRef = $output[count($output) - 2]['value'] ?? '';
}
preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/miu', $rangeStartCellRef, $rangeStartMatches);
if ($rangeStartMatches[2] !== $matches[2]) {
if (isset($rangeStartMatches[2]) && $rangeStartMatches[2] !== $matches[2]) {
return $this->raiseFormulaError('3D Range references are not yet supported');
}
}
Expand Down Expand Up @@ -4380,7 +4382,7 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
$valx = $val;
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataColumn($valx) : AddressRange::MAX_COLUMN; // Max 16,384 columns for Excel2007
$val = "{$rangeWS2}{$endRowColRef}{$val}";
} elseif (ctype_alpha($val) && strlen($val ?? '') <= 3) {
} elseif (ctype_alpha($val) && is_string($val) && strlen($val) <= 3) {
// Column range
$stackItemType = 'Column Reference';
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestDataRow($val) : AddressRange::MAX_ROW; // Max 1,048,576 rows for Excel2007
Expand Down Expand Up @@ -4545,6 +4547,12 @@ private static function dataTestReference(array &$operandData): mixed
return $operand;
}

private static int $matchIndex8 = 8;

private static int $matchIndex9 = 9;

private static int $matchIndex10 = 10;

/**
* @return array<int, mixed>|false
*/
Expand Down Expand Up @@ -4908,12 +4916,17 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
} elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $token ?? '', $matches)) {
$cellRef = null;

if (isset($matches[8])) {
/* Phpstan says matches[8/9/10] is never set,
and code coverage report seems to confirm.
Appease PhpStan for now;
probably delete this block later.
*/
if (isset($matches[self::$matchIndex8])) {
if ($cell === null) {
// We can't access the range, so return a REF error
$cellValue = ExcelError::REF();
} else {
$cellRef = $matches[6] . $matches[7] . ':' . $matches[9] . $matches[10];
$cellRef = $matches[6] . $matches[7] . ':' . $matches[self::$matchIndex9] . $matches[self::$matchIndex10];
if ($matches[2] > '') {
$matches[2] = trim($matches[2], "\"'");
if ((str_contains($matches[2], '[')) || (str_contains($matches[2], ']'))) {
Expand Down
6 changes: 4 additions & 2 deletions src/PhpSpreadsheet/Calculation/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,10 @@ public static function ifCondition(mixed $condition): string

return str_replace('""""', '""', '=' . $condition);
}
preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches);
[, $operator, $operand] = $matches;
$operator = $operand = '';
if (1 === preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches)) {
[, $operator, $operand] = $matches;
}

$operand = self::operandSpecialHandling($operand);
if (is_numeric(trim($operand, '"'))) {
Expand Down
9 changes: 5 additions & 4 deletions src/PhpSpreadsheet/Calculation/Information/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,11 @@ public static function isFormula(mixed $cellReference = '', ?Cell $cell = null):

$fullCellReference = Functions::trimTrailingRange($fullCellReference);

preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches);

$fullCellReference = $matches[6] . $matches[7];
$worksheetName = str_replace("''", "'", trim($matches[2], "'"));
$worksheetName = '';
if (1 == preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches)) {
$fullCellReference = $matches[6] . $matches[7];
$worksheetName = str_replace("''", "'", trim($matches[2], "'"));
}

$worksheet = (!empty($worksheetName))
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
Expand Down
15 changes: 8 additions & 7 deletions src/PhpSpreadsheet/Calculation/LookupRef/Formula.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ public static function text(mixed $cellReference = '', ?Cell $cell = null): stri
return ExcelError::REF();
}

preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches);

$cellReference = $matches[6] . $matches[7];
$worksheetName = trim($matches[3], "'");
$worksheet = (!empty($worksheetName))
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
: $cell->getWorksheet();
$worksheet = null;
if (1 === preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellReference, $matches)) {
$cellReference = $matches[6] . $matches[7];
$worksheetName = trim($matches[3], "'");
$worksheet = (!empty($worksheetName))
? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
: $cell->getWorksheet();
}

if (
$worksheet === null
Expand Down
4 changes: 1 addition & 3 deletions src/PhpSpreadsheet/Cell/AddressHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@ public static function convertToR1C1(
?int $currentRowNumber = null,
?int $currentColumnNumber = null
): string {
$validityCheck = preg_match(Coordinate::A1_COORDINATE_REGEX, $address, $cellReference);

if ($validityCheck === 0) {
if (1 !== preg_match(Coordinate::A1_COORDINATE_REGEX, $address, $cellReference)) {
throw new Exception('Invalid A1-format Cell Reference');
}

Expand Down
Loading

0 comments on commit d881cf8

Please sign in to comment.