commit
79d024fec0
|
@ -18,7 +18,7 @@ build:
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
external_code_coverage:
|
external_code_coverage:
|
||||||
timeout: 3600
|
timeout: 600
|
||||||
|
|
||||||
build_failure_conditions:
|
build_failure_conditions:
|
||||||
- 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed
|
- 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed
|
||||||
|
|
|
@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
- Fix RATE, PRICE, XIRR, and XNPV Functions [#1456](https://github.com/PHPOffice/PhpSpreadsheet/pull/1456)
|
- Fix RATE, PRICE, XIRR, and XNPV Functions [#1456](https://github.com/PHPOffice/PhpSpreadsheet/pull/1456)
|
||||||
- Save Excel 2010+ functions properly in XLSX [#1461](https://github.com/PHPOffice/PhpSpreadsheet/pull/1461)
|
- Save Excel 2010+ functions properly in XLSX [#1461](https://github.com/PHPOffice/PhpSpreadsheet/pull/1461)
|
||||||
- Several improvements in HTML writer [#1464](https://github.com/PHPOffice/PhpSpreadsheet/pull/1464)
|
- Several improvements in HTML writer [#1464](https://github.com/PHPOffice/PhpSpreadsheet/pull/1464)
|
||||||
|
- Fix incorrect behaviour when saving XLSX file with drawings [#1462](https://github.com/PHPOffice/PhpSpreadsheet/pull/1462),
|
||||||
|
- Fix Crash while trying setting a cell the value "123456\n" [#1476](https://github.com/PHPOffice/PhpSpreadsheet/pull/1481)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,4 @@ $helper->logRead('Xlsx', $filename, $callStartTime);
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
$helper->write($spreadsheet, __FILE__);
|
$helper->write($spreadsheet, __FILE__);
|
||||||
|
unlink($filename);
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
use PhpOffice\PhpSpreadsheet\Reader\Csv as CsvReader;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Writer\Csv as CsvWriter;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
||||||
|
|
||||||
$helper->log('Write to CSV format');
|
$helper->log('Write to CSV format');
|
||||||
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writer */
|
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writer */
|
||||||
$writer = IOFactory::createWriter($spreadsheet, 'Csv')->setDelimiter(',')
|
$writer = new CsvWriter($spreadsheet);
|
||||||
|
$writer->setDelimiter(',')
|
||||||
->setEnclosure('"')
|
->setEnclosure('"')
|
||||||
->setSheetIndex(0);
|
->setSheetIndex(0);
|
||||||
|
|
||||||
|
@ -19,13 +21,15 @@ $helper->logWrite($writer, $filename, $callStartTime);
|
||||||
$helper->log('Read from CSV format');
|
$helper->log('Read from CSV format');
|
||||||
|
|
||||||
/** @var \PhpOffice\PhpSpreadsheet\Reader\Csv $reader */
|
/** @var \PhpOffice\PhpSpreadsheet\Reader\Csv $reader */
|
||||||
$reader = IOFactory::createReader('Csv')->setDelimiter(',')
|
$reader = new CsvReader();
|
||||||
|
$reader->setDelimiter(',')
|
||||||
->setEnclosure('"')
|
->setEnclosure('"')
|
||||||
->setSheetIndex(0);
|
->setSheetIndex(0);
|
||||||
|
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$spreadsheetFromCSV = $reader->load($filename);
|
$spreadsheetFromCSV = $reader->load($filename);
|
||||||
$helper->logRead('Csv', $filename, $callStartTime);
|
$helper->logRead('Csv', $filename, $callStartTime);
|
||||||
|
unlink($filename);
|
||||||
|
|
||||||
// Write Xlsx
|
// Write Xlsx
|
||||||
$helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
|
$helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
|
||||||
|
@ -33,7 +37,7 @@ $helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
|
||||||
// Write CSV
|
// Write CSV
|
||||||
$filenameCSV = $helper->getFilename(__FILE__, 'csv');
|
$filenameCSV = $helper->getFilename(__FILE__, 'csv');
|
||||||
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writerCSV */
|
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writerCSV */
|
||||||
$writerCSV = IOFactory::createWriter($spreadsheetFromCSV, 'Csv');
|
$writerCSV = new CsvWriter($spreadsheetFromCSV);
|
||||||
$writerCSV->setExcelCompatibility(true);
|
$writerCSV->setExcelCompatibility(true);
|
||||||
|
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
|
|
|
@ -17,6 +17,7 @@ $helper->logWrite($writer, $filename, $callStartTime);
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$spreadsheet = IOFactory::load($filename);
|
$spreadsheet = IOFactory::load($filename);
|
||||||
$helper->logRead('Xls', $filename, $callStartTime);
|
$helper->logRead('Xls', $filename, $callStartTime);
|
||||||
|
unlink($filename);
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
$helper->write($spreadsheet, __FILE__);
|
$helper->write($spreadsheet, __FILE__);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace PhpOffice\PhpSpreadsheet;
|
namespace PhpOffice\PhpSpreadsheet;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
|
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
|
@ -29,10 +30,11 @@ class MyReadFilter implements IReadFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
$helper->log('Load from Xlsx file');
|
$helper->log('Load from Xlsx file');
|
||||||
$reader = IOFactory::createReader('Xlsx');
|
$reader = new XlsxReader();
|
||||||
$reader->setReadFilter(new MyReadFilter());
|
$reader->setReadFilter(new MyReadFilter());
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$spreadsheet = $reader->load($filename);
|
$spreadsheet = $reader->load($filename);
|
||||||
|
unlink($filename);
|
||||||
$helper->logRead('Xlsx', $filename, $callStartTime);
|
$helper->logRead('Xlsx', $filename, $callStartTime);
|
||||||
$helper->log('Remove unnecessary rows');
|
$helper->log('Remove unnecessary rows');
|
||||||
$spreadsheet->getActiveSheet()->removeRow(2, 18);
|
$spreadsheet->getActiveSheet()->removeRow(2, 18);
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XLsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XLsxWriter;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
|
|
||||||
$sampleSpreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
$sampleSpreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
|
||||||
$filename = $helper->getTemporaryFilename();
|
$filename = $helper->getTemporaryFilename();
|
||||||
$writer = new Xlsx($sampleSpreadsheet);
|
$writer = new XlsxWriter($sampleSpreadsheet);
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
$helper->logWrite($writer, $filename, $callStartTime);
|
$helper->logWrite($writer, $filename, $callStartTime);
|
||||||
|
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$reader = IOFactory::createReader('Xlsx');
|
$reader = new XlsxReader();
|
||||||
$spreadsheet = $reader->load($filename);
|
$spreadsheet = $reader->load($filename);
|
||||||
$helper->logRead('Xlsx', $filename, $callStartTime);
|
$helper->logRead('Xlsx', $filename, $callStartTime);
|
||||||
|
unlink($filename);
|
||||||
$helper->log('Iterate worksheets');
|
$helper->log('Iterate worksheets');
|
||||||
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
|
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
|
||||||
$helper->log('Worksheet - ' . $worksheet->getTitle());
|
$helper->log('Worksheet - ' . $worksheet->getTitle());
|
||||||
|
|
|
@ -24,3 +24,5 @@ var_dump($sheetList);
|
||||||
|
|
||||||
$helper->log('Worksheet Names:');
|
$helper->log('Worksheet Names:');
|
||||||
var_dump($sheetInfo);
|
var_dump($sheetInfo);
|
||||||
|
|
||||||
|
unlink($filename);
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
|
||||||
|
|
||||||
require __DIR__ . '/../Header.php';
|
require __DIR__ . '/../Header.php';
|
||||||
|
|
||||||
// Create temporary file that will be read
|
// Create temporary file that will be read
|
||||||
$sampleSpreadsheet = require __DIR__ . '/../templates/chartSpreadsheet.php';
|
$sampleSpreadsheet = require __DIR__ . '/../templates/chartSpreadsheet.php';
|
||||||
$filename = $helper->getTemporaryFilename();
|
$filename = $helper->getTemporaryFilename();
|
||||||
$writer = new Xlsx($sampleSpreadsheet);
|
$writer = new XlsxWriter($sampleSpreadsheet);
|
||||||
|
$writer->setIncludeCharts(true);
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
|
|
||||||
$helper->log('Load from Xlsx file');
|
$helper->log('Load from Xlsx file');
|
||||||
$reader = IOFactory::createReader('Xlsx');
|
$reader = new XlsxReader();
|
||||||
$reader->setIncludeCharts(true);
|
$reader->setIncludeCharts(true);
|
||||||
$spreadsheet = $reader->load($filename);
|
$spreadsheet = $reader->load($filename);
|
||||||
|
unlink($filename);
|
||||||
|
|
||||||
$helper->log('Update cell data values that are displayed in the chart');
|
$helper->log('Update cell data values that are displayed in the chart');
|
||||||
$worksheet = $spreadsheet->getActiveSheet();
|
$worksheet = $spreadsheet->getActiveSheet();
|
||||||
|
@ -31,7 +33,7 @@ $worksheet->fromArray(
|
||||||
|
|
||||||
// Save Excel 2007 file
|
// Save Excel 2007 file
|
||||||
$filename = $helper->getFilename(__FILE__);
|
$filename = $helper->getFilename(__FILE__);
|
||||||
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
|
$writer = new XlsxWriter($spreadsheet);
|
||||||
$writer->setIncludeCharts(true);
|
$writer->setIncludeCharts(true);
|
||||||
$callStartTime = microtime(true);
|
$callStartTime = microtime(true);
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
|
|
|
@ -37,6 +37,10 @@ class Calculation
|
||||||
const RETURN_ARRAY_AS_VALUE = 'value';
|
const RETURN_ARRAY_AS_VALUE = 'value';
|
||||||
const RETURN_ARRAY_AS_ARRAY = 'array';
|
const RETURN_ARRAY_AS_ARRAY = 'array';
|
||||||
|
|
||||||
|
const FORMULA_OPEN_FUNCTION_BRACE = '{';
|
||||||
|
const FORMULA_CLOSE_FUNCTION_BRACE = '}';
|
||||||
|
const FORMULA_STRING_QUOTE = '"';
|
||||||
|
|
||||||
private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE;
|
private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2593,11 +2597,11 @@ class Calculation
|
||||||
for ($i = 0; $i < $strlen; ++$i) {
|
for ($i = 0; $i < $strlen; ++$i) {
|
||||||
$chr = mb_substr($formula, $i, 1);
|
$chr = mb_substr($formula, $i, 1);
|
||||||
switch ($chr) {
|
switch ($chr) {
|
||||||
case '{':
|
case self::FORMULA_OPEN_FUNCTION_BRACE:
|
||||||
$inBraces = true;
|
$inBraces = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case '}':
|
case self::FORMULA_CLOSE_FUNCTION_BRACE:
|
||||||
$inBraces = false;
|
$inBraces = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -2626,10 +2630,10 @@ class Calculation
|
||||||
if (self::$localeLanguage !== 'en_us') {
|
if (self::$localeLanguage !== 'en_us') {
|
||||||
$inBraces = false;
|
$inBraces = false;
|
||||||
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
|
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
|
||||||
if (strpos($formula, '"') !== false) {
|
if (strpos($formula, self::FORMULA_STRING_QUOTE) !== false) {
|
||||||
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
|
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
|
||||||
// the formula
|
// the formula
|
||||||
$temp = explode('"', $formula);
|
$temp = explode(self::FORMULA_STRING_QUOTE, $formula);
|
||||||
$i = false;
|
$i = false;
|
||||||
foreach ($temp as &$value) {
|
foreach ($temp as &$value) {
|
||||||
// Only count/replace in alternating array entries
|
// Only count/replace in alternating array entries
|
||||||
|
@ -2640,7 +2644,7 @@ class Calculation
|
||||||
}
|
}
|
||||||
unset($value);
|
unset($value);
|
||||||
// Then rebuild the formula string
|
// Then rebuild the formula string
|
||||||
$formula = implode('"', $temp);
|
$formula = implode(self::FORMULA_STRING_QUOTE, $temp);
|
||||||
} else {
|
} else {
|
||||||
// If there's no quoted strings, then we do a simple count/replace
|
// If there's no quoted strings, then we do a simple count/replace
|
||||||
$formula = preg_replace($from, $to, $formula);
|
$formula = preg_replace($from, $to, $formula);
|
||||||
|
@ -2741,7 +2745,7 @@ class Calculation
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
// Return strings wrapped in quotes
|
// Return strings wrapped in quotes
|
||||||
return '"' . $value . '"';
|
return self::FORMULA_STRING_QUOTE . $value . self::FORMULA_STRING_QUOTE;
|
||||||
// Convert numeric errors to NaN error
|
// Convert numeric errors to NaN error
|
||||||
} elseif ((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
|
} elseif ((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
|
@ -2760,7 +2764,7 @@ class Calculation
|
||||||
public static function unwrapResult($value)
|
public static function unwrapResult($value)
|
||||||
{
|
{
|
||||||
if (is_string($value)) {
|
if (is_string($value)) {
|
||||||
if ((isset($value[0])) && ($value[0] == '"') && (substr($value, -1) == '"')) {
|
if ((isset($value[0])) && ($value[0] == self::FORMULA_STRING_QUOTE) && (substr($value, -1) == self::FORMULA_STRING_QUOTE)) {
|
||||||
return substr($value, 1, -1);
|
return substr($value, 1, -1);
|
||||||
}
|
}
|
||||||
// Convert numeric errors to NAN error
|
// Convert numeric errors to NAN error
|
||||||
|
@ -3227,8 +3231,8 @@ class Calculation
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{ ' . implode($rpad, $returnMatrix) . ' }';
|
return '{ ' . implode($rpad, $returnMatrix) . ' }';
|
||||||
} elseif (is_string($value) && (trim($value, '"') == $value)) {
|
} elseif (is_string($value) && (trim($value, self::FORMULA_STRING_QUOTE) == $value)) {
|
||||||
return '"' . $value . '"';
|
return self::FORMULA_STRING_QUOTE . $value . self::FORMULA_STRING_QUOTE;
|
||||||
} elseif (is_bool($value)) {
|
} elseif (is_bool($value)) {
|
||||||
return ($value) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE'];
|
return ($value) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE'];
|
||||||
}
|
}
|
||||||
|
@ -3282,34 +3286,34 @@ class Calculation
|
||||||
*/
|
*/
|
||||||
private function convertMatrixReferences($formula)
|
private function convertMatrixReferences($formula)
|
||||||
{
|
{
|
||||||
static $matrixReplaceFrom = ['{', ';', '}'];
|
static $matrixReplaceFrom = [self::FORMULA_OPEN_FUNCTION_BRACE, ';', self::FORMULA_CLOSE_FUNCTION_BRACE];
|
||||||
static $matrixReplaceTo = ['MKMATRIX(MKMATRIX(', '),MKMATRIX(', '))'];
|
static $matrixReplaceTo = ['MKMATRIX(MKMATRIX(', '),MKMATRIX(', '))'];
|
||||||
|
|
||||||
// Convert any Excel matrix references to the MKMATRIX() function
|
// Convert any Excel matrix references to the MKMATRIX() function
|
||||||
if (strpos($formula, '{') !== false) {
|
if (strpos($formula, self::FORMULA_OPEN_FUNCTION_BRACE) !== false) {
|
||||||
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
|
// If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators
|
||||||
if (strpos($formula, '"') !== false) {
|
if (strpos($formula, self::FORMULA_STRING_QUOTE) !== false) {
|
||||||
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
|
// So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded
|
||||||
// the formula
|
// the formula
|
||||||
$temp = explode('"', $formula);
|
$temp = explode(self::FORMULA_STRING_QUOTE, $formula);
|
||||||
// Open and Closed counts used for trapping mismatched braces in the formula
|
// Open and Closed counts used for trapping mismatched braces in the formula
|
||||||
$openCount = $closeCount = 0;
|
$openCount = $closeCount = 0;
|
||||||
$i = false;
|
$i = false;
|
||||||
foreach ($temp as &$value) {
|
foreach ($temp as &$value) {
|
||||||
// Only count/replace in alternating array entries
|
// Only count/replace in alternating array entries
|
||||||
if ($i = !$i) {
|
if ($i = !$i) {
|
||||||
$openCount += substr_count($value, '{');
|
$openCount += substr_count($value, self::FORMULA_OPEN_FUNCTION_BRACE);
|
||||||
$closeCount += substr_count($value, '}');
|
$closeCount += substr_count($value, self::FORMULA_CLOSE_FUNCTION_BRACE);
|
||||||
$value = str_replace($matrixReplaceFrom, $matrixReplaceTo, $value);
|
$value = str_replace($matrixReplaceFrom, $matrixReplaceTo, $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unset($value);
|
unset($value);
|
||||||
// Then rebuild the formula string
|
// Then rebuild the formula string
|
||||||
$formula = implode('"', $temp);
|
$formula = implode(self::FORMULA_STRING_QUOTE, $temp);
|
||||||
} else {
|
} else {
|
||||||
// If there's no quoted strings, then we do a simple count/replace
|
// If there's no quoted strings, then we do a simple count/replace
|
||||||
$openCount = substr_count($formula, '{');
|
$openCount = substr_count($formula, self::FORMULA_OPEN_FUNCTION_BRACE);
|
||||||
$closeCount = substr_count($formula, '}');
|
$closeCount = substr_count($formula, self::FORMULA_CLOSE_FUNCTION_BRACE);
|
||||||
$formula = str_replace($matrixReplaceFrom, $matrixReplaceTo, $formula);
|
$formula = str_replace($matrixReplaceFrom, $matrixReplaceTo, $formula);
|
||||||
}
|
}
|
||||||
// Trap for mismatched braces and trigger an appropriate error
|
// Trap for mismatched braces and trigger an appropriate error
|
||||||
|
@ -3715,9 +3719,9 @@ class Calculation
|
||||||
}
|
}
|
||||||
|
|
||||||
$localeConstant = false;
|
$localeConstant = false;
|
||||||
if ($opCharacter == '"') {
|
if ($opCharacter == self::FORMULA_STRING_QUOTE) {
|
||||||
// UnEscape any quotes within the string
|
// UnEscape any quotes within the string
|
||||||
$val = self::wrapResult(str_replace('""', '"', self::unwrapResult($val)));
|
$val = self::wrapResult(str_replace('""', self::FORMULA_STRING_QUOTE, self::unwrapResult($val)));
|
||||||
} elseif (is_numeric($val)) {
|
} elseif (is_numeric($val)) {
|
||||||
if ((strpos($val, '.') !== false) || (stripos($val, 'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
|
if ((strpos($val, '.') !== false) || (stripos($val, 'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
|
||||||
$val = (float) $val;
|
$val = (float) $val;
|
||||||
|
@ -4058,7 +4062,7 @@ class Calculation
|
||||||
$result = '#VALUE!';
|
$result = '#VALUE!';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$result = '"' . str_replace('""', '"', self::unwrapResult($operand1) . self::unwrapResult($operand2)) . '"';
|
$result = self::FORMULA_STRING_QUOTE . str_replace('""', self::FORMULA_STRING_QUOTE, self::unwrapResult($operand1) . self::unwrapResult($operand2)) . self::FORMULA_STRING_QUOTE;
|
||||||
}
|
}
|
||||||
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result));
|
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result));
|
||||||
$stack->push('Value', $result);
|
$stack->push('Value', $result);
|
||||||
|
@ -4078,9 +4082,15 @@ class Calculation
|
||||||
$cellIntersect[$row] = array_intersect_key($operand1[$row], $operand2[$row]);
|
$cellIntersect[$row] = array_intersect_key($operand1[$row], $operand2[$row]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cellRef = Coordinate::stringFromColumnIndex(min($oCol) + 1) . min($oRow) . ':' . Coordinate::stringFromColumnIndex(max($oCol) + 1) . max($oRow);
|
if (count(Functions::flattenArray($cellIntersect)) === 0) {
|
||||||
|
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($cellIntersect));
|
||||||
|
$stack->push('Error', Functions::null(), null);
|
||||||
|
} else {
|
||||||
|
$cellRef = Coordinate::stringFromColumnIndex(min($oCol) + 1) . min($oRow) . ':' .
|
||||||
|
Coordinate::stringFromColumnIndex(max($oCol) + 1) . max($oRow);
|
||||||
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($cellIntersect));
|
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($cellIntersect));
|
||||||
$stack->push('Value', $cellIntersect, $cellRef);
|
$stack->push('Value', $cellIntersect, $cellRef);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4284,7 +4294,7 @@ class Calculation
|
||||||
$branchStore[$storeKey] = self::$excelConstants[$excelConstant];
|
$branchStore[$storeKey] = self::$excelConstants[$excelConstant];
|
||||||
}
|
}
|
||||||
$this->debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->showTypeDetails(self::$excelConstants[$excelConstant]));
|
$this->debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->showTypeDetails(self::$excelConstants[$excelConstant]));
|
||||||
} elseif ((is_numeric($token)) || ($token === null) || (is_bool($token)) || ($token == '') || ($token[0] == '"') || ($token[0] == '#')) {
|
} elseif ((is_numeric($token)) || ($token === null) || (is_bool($token)) || ($token == '') || ($token[0] == self::FORMULA_STRING_QUOTE) || ($token[0] == '#')) {
|
||||||
$stack->push('Value', $token);
|
$stack->push('Value', $token);
|
||||||
if (isset($storeKey)) {
|
if (isset($storeKey)) {
|
||||||
$branchStore[$storeKey] = $token;
|
$branchStore[$storeKey] = $token;
|
||||||
|
@ -4329,7 +4339,7 @@ class Calculation
|
||||||
if (is_string($operand)) {
|
if (is_string($operand)) {
|
||||||
// We only need special validations for the operand if it is a string
|
// We only need special validations for the operand if it is a string
|
||||||
// Start by stripping off the quotation marks we use to identify true excel string values internally
|
// Start by stripping off the quotation marks we use to identify true excel string values internally
|
||||||
if ($operand > '' && $operand[0] == '"') {
|
if ($operand > '' && $operand[0] == self::FORMULA_STRING_QUOTE) {
|
||||||
$operand = self::unwrapResult($operand);
|
$operand = self::unwrapResult($operand);
|
||||||
}
|
}
|
||||||
// If the string is a numeric value, we treat it as a numeric, so no further testing
|
// If the string is a numeric value, we treat it as a numeric, so no further testing
|
||||||
|
@ -4342,7 +4352,7 @@ class Calculation
|
||||||
return false;
|
return false;
|
||||||
} elseif (!Shared\StringHelper::convertToNumberIfFraction($operand)) {
|
} elseif (!Shared\StringHelper::convertToNumberIfFraction($operand)) {
|
||||||
// If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations
|
// If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations
|
||||||
$stack->push('Value', '#VALUE!');
|
$stack->push('Error', '#VALUE!');
|
||||||
$this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!'));
|
$this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!'));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -4402,10 +4412,10 @@ class Calculation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple validate the two operands if they are string values
|
// Simple validate the two operands if they are string values
|
||||||
if (is_string($operand1) && $operand1 > '' && $operand1[0] == '"') {
|
if (is_string($operand1) && $operand1 > '' && $operand1[0] == self::FORMULA_STRING_QUOTE) {
|
||||||
$operand1 = self::unwrapResult($operand1);
|
$operand1 = self::unwrapResult($operand1);
|
||||||
}
|
}
|
||||||
if (is_string($operand2) && $operand2 > '' && $operand2[0] == '"') {
|
if (is_string($operand2) && $operand2 > '' && $operand2[0] == self::FORMULA_STRING_QUOTE) {
|
||||||
$operand2 = self::unwrapResult($operand2);
|
$operand2 = self::unwrapResult($operand2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4570,7 +4580,7 @@ class Calculation
|
||||||
case '/':
|
case '/':
|
||||||
if ($operand2 == 0) {
|
if ($operand2 == 0) {
|
||||||
// Trap for Divide by Zero error
|
// Trap for Divide by Zero error
|
||||||
$stack->push('Value', '#DIV/0!');
|
$stack->push('Error', '#DIV/0!');
|
||||||
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails('#DIV/0!'));
|
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails('#DIV/0!'));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1339,6 +1339,8 @@ class MathTrig
|
||||||
// Is it a numeric value?
|
// Is it a numeric value?
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
$returnValue += $arg;
|
$returnValue += $arg;
|
||||||
|
} elseif (Functions::isError($arg)) {
|
||||||
|
return $arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ class DefaultValueBinder implements IValueBinder
|
||||||
return DataType::TYPE_STRING;
|
return DataType::TYPE_STRING;
|
||||||
} elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) {
|
} elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) {
|
||||||
return DataType::TYPE_STRING;
|
return DataType::TYPE_STRING;
|
||||||
|
} elseif (!is_numeric($pValue)) {
|
||||||
|
return DataType::TYPE_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataType::TYPE_NUMERIC;
|
return DataType::TYPE_NUMERIC;
|
||||||
|
|
|
@ -933,7 +933,12 @@ class Html extends BaseReader
|
||||||
*/
|
*/
|
||||||
private function setBorderStyle(Style $cellStyle, $styleValue, $type): void
|
private function setBorderStyle(Style $cellStyle, $styleValue, $type): void
|
||||||
{
|
{
|
||||||
|
if (trim($styleValue) === Border::BORDER_NONE) {
|
||||||
|
$borderStyle = Border::BORDER_NONE;
|
||||||
|
$color = null;
|
||||||
|
} else {
|
||||||
[, $borderStyle, $color] = explode(' ', $styleValue);
|
[, $borderStyle, $color] = explode(' ', $styleValue);
|
||||||
|
}
|
||||||
|
|
||||||
$cellStyle->applyFromArray([
|
$cellStyle->applyFromArray([
|
||||||
'borders' => [
|
'borders' => [
|
||||||
|
|
|
@ -1000,12 +1000,13 @@ class Xlsx extends BaseReader
|
||||||
Settings::getLibXmlLoaderOptions()
|
Settings::getLibXmlLoaderOptions()
|
||||||
);
|
);
|
||||||
$drawings = [];
|
$drawings = [];
|
||||||
|
if (isset($relsVML->Relationship)) {
|
||||||
foreach ($relsVML->Relationship as $ele) {
|
foreach ($relsVML->Relationship as $ele) {
|
||||||
if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
|
if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
|
||||||
$drawings[(string) $ele['Id']] = self::dirAdd($vmlRelationship, $ele['Target']);
|
$drawings[(string) $ele['Id']] = self::dirAdd($vmlRelationship, $ele['Target']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Fetch VML document
|
// Fetch VML document
|
||||||
$vmlDrawing = simplexml_load_string(
|
$vmlDrawing = simplexml_load_string(
|
||||||
$this->securityScanner->scan($this->getFromZipArchive($zip, $vmlRelationship)),
|
$this->securityScanner->scan($this->getFromZipArchive($zip, $vmlRelationship)),
|
||||||
|
|
|
@ -6,6 +6,65 @@ use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
|
|
||||||
class CodePage
|
class CodePage
|
||||||
{
|
{
|
||||||
|
private static $pageArray = [
|
||||||
|
0 => 'CP1252', // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program
|
||||||
|
367 => 'ASCII', // ASCII
|
||||||
|
437 => 'CP437', // OEM US
|
||||||
|
//720 => 'notsupported', // OEM Arabic
|
||||||
|
737 => 'CP737', // OEM Greek
|
||||||
|
775 => 'CP775', // OEM Baltic
|
||||||
|
850 => 'CP850', // OEM Latin I
|
||||||
|
852 => 'CP852', // OEM Latin II (Central European)
|
||||||
|
855 => 'CP855', // OEM Cyrillic
|
||||||
|
857 => 'CP857', // OEM Turkish
|
||||||
|
858 => 'CP858', // OEM Multilingual Latin I with Euro
|
||||||
|
860 => 'CP860', // OEM Portugese
|
||||||
|
861 => 'CP861', // OEM Icelandic
|
||||||
|
862 => 'CP862', // OEM Hebrew
|
||||||
|
863 => 'CP863', // OEM Canadian (French)
|
||||||
|
864 => 'CP864', // OEM Arabic
|
||||||
|
865 => 'CP865', // OEM Nordic
|
||||||
|
866 => 'CP866', // OEM Cyrillic (Russian)
|
||||||
|
869 => 'CP869', // OEM Greek (Modern)
|
||||||
|
874 => 'CP874', // ANSI Thai
|
||||||
|
932 => 'CP932', // ANSI Japanese Shift-JIS
|
||||||
|
936 => 'CP936', // ANSI Chinese Simplified GBK
|
||||||
|
949 => 'CP949', // ANSI Korean (Wansung)
|
||||||
|
950 => 'CP950', // ANSI Chinese Traditional BIG5
|
||||||
|
1200 => 'UTF-16LE', // UTF-16 (BIFF8)
|
||||||
|
1250 => 'CP1250', // ANSI Latin II (Central European)
|
||||||
|
1251 => 'CP1251', // ANSI Cyrillic
|
||||||
|
1252 => 'CP1252', // ANSI Latin I (BIFF4-BIFF7)
|
||||||
|
1253 => 'CP1253', // ANSI Greek
|
||||||
|
1254 => 'CP1254', // ANSI Turkish
|
||||||
|
1255 => 'CP1255', // ANSI Hebrew
|
||||||
|
1256 => 'CP1256', // ANSI Arabic
|
||||||
|
1257 => 'CP1257', // ANSI Baltic
|
||||||
|
1258 => 'CP1258', // ANSI Vietnamese
|
||||||
|
1361 => 'CP1361', // ANSI Korean (Johab)
|
||||||
|
10000 => 'MAC', // Apple Roman
|
||||||
|
10001 => 'CP932', // Macintosh Japanese
|
||||||
|
10002 => 'CP950', // Macintosh Chinese Traditional
|
||||||
|
10003 => 'CP1361', // Macintosh Korean
|
||||||
|
10004 => 'MACARABIC', // Apple Arabic
|
||||||
|
10005 => 'MACHEBREW', // Apple Hebrew
|
||||||
|
10006 => 'MACGREEK', // Macintosh Greek
|
||||||
|
10007 => 'MACCYRILLIC', // Macintosh Cyrillic
|
||||||
|
10008 => 'CP936', // Macintosh - Simplified Chinese (GB 2312)
|
||||||
|
10010 => 'MACROMANIA', // Macintosh Romania
|
||||||
|
10017 => 'MACUKRAINE', // Macintosh Ukraine
|
||||||
|
10021 => 'MACTHAI', // Macintosh Thai
|
||||||
|
10029 => 'MACCENTRALEUROPE', // Macintosh Central Europe
|
||||||
|
10079 => 'MACICELAND', // Macintosh Icelandic
|
||||||
|
10081 => 'MACTURKISH', // Macintosh Turkish
|
||||||
|
10082 => 'MACCROATIAN', // Macintosh Croatian
|
||||||
|
21010 => 'UTF-16LE', // UTF-16 (BIFF8) This isn't correct, but some Excel writer libraries erroneously use Codepage 21010 for UTF-16LE
|
||||||
|
32768 => 'MAC', // Apple Roman
|
||||||
|
//32769 => 'unsupported', // ANSI Latin I (BIFF2-BIFF3)
|
||||||
|
65000 => 'UTF-7', // Unicode (UTF-7)
|
||||||
|
65001 => 'UTF-8', // Unicode (UTF-8)
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
|
* Convert Microsoft Code Page Identifier to Code Page Name which iconv
|
||||||
* and mbstring understands.
|
* and mbstring understands.
|
||||||
|
@ -14,123 +73,20 @@ class CodePage
|
||||||
*
|
*
|
||||||
* @return string Code Page Name
|
* @return string Code Page Name
|
||||||
*/
|
*/
|
||||||
public static function numberToName($codePage)
|
public static function numberToName(int $codePage): string
|
||||||
{
|
{
|
||||||
switch ($codePage) {
|
if (array_key_exists($codePage, self::$pageArray)) {
|
||||||
case 367:
|
return self::$pageArray[$codePage];
|
||||||
return 'ASCII'; // ASCII
|
}
|
||||||
case 437:
|
if ($codePage == 720 || $codePage == 32769) {
|
||||||
return 'CP437'; // OEM US
|
throw new PhpSpreadsheetException("Code page $codePage not supported."); // OEM Arabic
|
||||||
case 720:
|
|
||||||
throw new PhpSpreadsheetException('Code page 720 not supported.'); // OEM Arabic
|
|
||||||
case 737:
|
|
||||||
return 'CP737'; // OEM Greek
|
|
||||||
case 775:
|
|
||||||
return 'CP775'; // OEM Baltic
|
|
||||||
case 850:
|
|
||||||
return 'CP850'; // OEM Latin I
|
|
||||||
case 852:
|
|
||||||
return 'CP852'; // OEM Latin II (Central European)
|
|
||||||
case 855:
|
|
||||||
return 'CP855'; // OEM Cyrillic
|
|
||||||
case 857:
|
|
||||||
return 'CP857'; // OEM Turkish
|
|
||||||
case 858:
|
|
||||||
return 'CP858'; // OEM Multilingual Latin I with Euro
|
|
||||||
case 860:
|
|
||||||
return 'CP860'; // OEM Portugese
|
|
||||||
case 861:
|
|
||||||
return 'CP861'; // OEM Icelandic
|
|
||||||
case 862:
|
|
||||||
return 'CP862'; // OEM Hebrew
|
|
||||||
case 863:
|
|
||||||
return 'CP863'; // OEM Canadian (French)
|
|
||||||
case 864:
|
|
||||||
return 'CP864'; // OEM Arabic
|
|
||||||
case 865:
|
|
||||||
return 'CP865'; // OEM Nordic
|
|
||||||
case 866:
|
|
||||||
return 'CP866'; // OEM Cyrillic (Russian)
|
|
||||||
case 869:
|
|
||||||
return 'CP869'; // OEM Greek (Modern)
|
|
||||||
case 874:
|
|
||||||
return 'CP874'; // ANSI Thai
|
|
||||||
case 932:
|
|
||||||
return 'CP932'; // ANSI Japanese Shift-JIS
|
|
||||||
case 936:
|
|
||||||
return 'CP936'; // ANSI Chinese Simplified GBK
|
|
||||||
case 949:
|
|
||||||
return 'CP949'; // ANSI Korean (Wansung)
|
|
||||||
case 950:
|
|
||||||
return 'CP950'; // ANSI Chinese Traditional BIG5
|
|
||||||
case 1200:
|
|
||||||
return 'UTF-16LE'; // UTF-16 (BIFF8)
|
|
||||||
case 1250:
|
|
||||||
return 'CP1250'; // ANSI Latin II (Central European)
|
|
||||||
case 1251:
|
|
||||||
return 'CP1251'; // ANSI Cyrillic
|
|
||||||
case 0:
|
|
||||||
// CodePage is not always correctly set when the xls file was saved by Apple's Numbers program
|
|
||||||
case 1252:
|
|
||||||
return 'CP1252'; // ANSI Latin I (BIFF4-BIFF7)
|
|
||||||
case 1253:
|
|
||||||
return 'CP1253'; // ANSI Greek
|
|
||||||
case 1254:
|
|
||||||
return 'CP1254'; // ANSI Turkish
|
|
||||||
case 1255:
|
|
||||||
return 'CP1255'; // ANSI Hebrew
|
|
||||||
case 1256:
|
|
||||||
return 'CP1256'; // ANSI Arabic
|
|
||||||
case 1257:
|
|
||||||
return 'CP1257'; // ANSI Baltic
|
|
||||||
case 1258:
|
|
||||||
return 'CP1258'; // ANSI Vietnamese
|
|
||||||
case 1361:
|
|
||||||
return 'CP1361'; // ANSI Korean (Johab)
|
|
||||||
case 10000:
|
|
||||||
return 'MAC'; // Apple Roman
|
|
||||||
case 10001:
|
|
||||||
return 'CP932'; // Macintosh Japanese
|
|
||||||
case 10002:
|
|
||||||
return 'CP950'; // Macintosh Chinese Traditional
|
|
||||||
case 10003:
|
|
||||||
return 'CP1361'; // Macintosh Korean
|
|
||||||
case 10004:
|
|
||||||
return 'MACARABIC'; // Apple Arabic
|
|
||||||
case 10005:
|
|
||||||
return 'MACHEBREW'; // Apple Hebrew
|
|
||||||
case 10006:
|
|
||||||
return 'MACGREEK'; // Macintosh Greek
|
|
||||||
case 10007:
|
|
||||||
return 'MACCYRILLIC'; // Macintosh Cyrillic
|
|
||||||
case 10008:
|
|
||||||
return 'CP936'; // Macintosh - Simplified Chinese (GB 2312)
|
|
||||||
case 10010:
|
|
||||||
return 'MACROMANIA'; // Macintosh Romania
|
|
||||||
case 10017:
|
|
||||||
return 'MACUKRAINE'; // Macintosh Ukraine
|
|
||||||
case 10021:
|
|
||||||
return 'MACTHAI'; // Macintosh Thai
|
|
||||||
case 10029:
|
|
||||||
return 'MACCENTRALEUROPE'; // Macintosh Central Europe
|
|
||||||
case 10079:
|
|
||||||
return 'MACICELAND'; // Macintosh Icelandic
|
|
||||||
case 10081:
|
|
||||||
return 'MACTURKISH'; // Macintosh Turkish
|
|
||||||
case 10082:
|
|
||||||
return 'MACCROATIAN'; // Macintosh Croatian
|
|
||||||
case 21010:
|
|
||||||
return 'UTF-16LE'; // UTF-16 (BIFF8) This isn't correct, but some Excel writer libraries erroneously use Codepage 21010 for UTF-16LE
|
|
||||||
case 32768:
|
|
||||||
return 'MAC'; // Apple Roman
|
|
||||||
case 32769:
|
|
||||||
throw new PhpSpreadsheetException('Code page 32769 not supported.'); // ANSI Latin I (BIFF2-BIFF3)
|
|
||||||
case 65000:
|
|
||||||
return 'UTF-7'; // Unicode (UTF-7)
|
|
||||||
case 65001:
|
|
||||||
return 'UTF-8'; // Unicode (UTF-8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new PhpSpreadsheetException('Unknown codepage: ' . $codePage);
|
throw new PhpSpreadsheetException('Unknown codepage: ' . $codePage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getEncodings(): array
|
||||||
|
{
|
||||||
|
return self::$pageArray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ namespace PhpOffice\PhpSpreadsheet\Shared;
|
||||||
|
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use Exception;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\DateTime;
|
use PhpOffice\PhpSpreadsheet\Calculation\DateTime;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
use PhpOffice\PhpSpreadsheet\Cell\Cell;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
|
|
||||||
class Date
|
class Date
|
||||||
|
@ -97,17 +97,18 @@ class Date
|
||||||
* @param DateTimeZone|string $timeZone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions
|
* @param DateTimeZone|string $timeZone The timezone to set for all Excel datetimestamp to PHP DateTime Object conversions
|
||||||
*
|
*
|
||||||
* @return bool Success or failure
|
* @return bool Success or failure
|
||||||
* @return bool Success or failure
|
|
||||||
*/
|
*/
|
||||||
public static function setDefaultTimezone($timeZone)
|
public static function setDefaultTimezone($timeZone)
|
||||||
{
|
{
|
||||||
if ($timeZone = self::validateTimeZone($timeZone)) {
|
try {
|
||||||
|
$timeZone = self::validateTimeZone($timeZone);
|
||||||
self::$defaultTimeZone = $timeZone;
|
self::$defaultTimeZone = $timeZone;
|
||||||
|
$retval = true;
|
||||||
return true;
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
$retval = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return $retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,17 +131,17 @@ class Date
|
||||||
* @param DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object
|
* @param DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object
|
||||||
*
|
*
|
||||||
* @return DateTimeZone The timezone as a timezone object
|
* @return DateTimeZone The timezone as a timezone object
|
||||||
* @return DateTimeZone The timezone as a timezone object
|
|
||||||
*/
|
*/
|
||||||
protected static function validateTimeZone($timeZone)
|
private static function validateTimeZone($timeZone)
|
||||||
{
|
{
|
||||||
if (is_object($timeZone) && $timeZone instanceof DateTimeZone) {
|
if ($timeZone instanceof DateTimeZone) {
|
||||||
return $timeZone;
|
return $timeZone;
|
||||||
} elseif (is_string($timeZone)) {
|
}
|
||||||
|
if (in_array($timeZone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC))) {
|
||||||
return new DateTimeZone($timeZone);
|
return new DateTimeZone($timeZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception('Invalid timezone');
|
throw new PhpSpreadsheetException('Invalid timezone');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -316,7 +317,7 @@ class Date
|
||||||
*/
|
*/
|
||||||
public static function isDateTime(Cell $pCell)
|
public static function isDateTime(Cell $pCell)
|
||||||
{
|
{
|
||||||
return is_numeric($pCell->getValue()) &&
|
return is_numeric($pCell->getCalculatedValue()) &&
|
||||||
self::isDateTimeFormat(
|
self::isDateTimeFormat(
|
||||||
$pCell->getWorksheet()->getStyle(
|
$pCell->getWorksheet()->getStyle(
|
||||||
$pCell->getCoordinate()
|
$pCell->getCoordinate()
|
||||||
|
|
|
@ -23,7 +23,7 @@ class TimeZone
|
||||||
*/
|
*/
|
||||||
private static function validateTimeZone($timezone)
|
private static function validateTimeZone($timezone)
|
||||||
{
|
{
|
||||||
return in_array($timezone, DateTimeZone::listIdentifiers());
|
return in_array($timezone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,10 +73,6 @@ class TimeZone
|
||||||
$timezone = self::$timezone;
|
$timezone = self::$timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($timezone == 'UST') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$objTimezone = new DateTimeZone($timezone);
|
$objTimezone = new DateTimeZone($timezone);
|
||||||
$transitions = $objTimezone->getTransitions($timestamp, $timestamp);
|
$transitions = $objTimezone->getTransitions($timestamp, $timestamp);
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,6 @@ class Rels extends WriterPart
|
||||||
$objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
|
$objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
|
||||||
|
|
||||||
// Write drawing relationships?
|
// Write drawing relationships?
|
||||||
$d = 0;
|
|
||||||
$drawingOriginalIds = [];
|
$drawingOriginalIds = [];
|
||||||
$unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
|
$unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
|
||||||
if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingOriginalIds'])) {
|
if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingOriginalIds'])) {
|
||||||
|
@ -197,13 +196,19 @@ class Rels extends WriterPart
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($pWorksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
|
if (($pWorksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
|
||||||
$relPath = '../drawings/drawing' . $pWorksheetId . '.xml';
|
$rId = 1;
|
||||||
$rId = ++$d;
|
|
||||||
|
|
||||||
|
// Use original $relPath to get original $rId.
|
||||||
|
// Take first. In future can be overwritten.
|
||||||
|
// (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeDrawings)
|
||||||
|
reset($drawingOriginalIds);
|
||||||
|
$relPath = key($drawingOriginalIds);
|
||||||
if (isset($drawingOriginalIds[$relPath])) {
|
if (isset($drawingOriginalIds[$relPath])) {
|
||||||
$rId = (int) (substr($drawingOriginalIds[$relPath], 3));
|
$rId = (int) (substr($drawingOriginalIds[$relPath], 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate new $relPath to write drawing relationship
|
||||||
|
$relPath = '../drawings/drawing' . $pWorksheetId . '.xml';
|
||||||
$this->writeRelationship(
|
$this->writeRelationship(
|
||||||
$objWriter,
|
$objWriter,
|
||||||
$rId,
|
$rId,
|
||||||
|
|
|
@ -1215,6 +1215,7 @@ class Worksheet extends WriterPart
|
||||||
if (isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'])) {
|
if (isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'])) {
|
||||||
$drawingOriginalIds = $unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'];
|
$drawingOriginalIds = $unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'];
|
||||||
// take first. In future can be overriten
|
// take first. In future can be overriten
|
||||||
|
// (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels::writeWorksheetRelationships)
|
||||||
$rId = reset($drawingOriginalIds);
|
$rId = reset($drawingOriginalIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,6 @@ class DefinedNameConfusedForCellTest extends TestCase
|
||||||
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
|
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
self::assertTrue(true);
|
self::assertTrue(true);
|
||||||
|
unlink($filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Engine;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class RangeTest extends TestCase
|
||||||
|
{
|
||||||
|
protected $spreadSheet;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->spreadSheet = new Spreadsheet();
|
||||||
|
$this->spreadSheet->getActiveSheet()
|
||||||
|
->setCellValue('A1', 1)
|
||||||
|
->setCellValue('B1', 2)
|
||||||
|
->setCellValue('C1', 3)
|
||||||
|
->setCellValue('A2', 4)
|
||||||
|
->setCellValue('B2', 5)
|
||||||
|
->setCellValue('C2', 6)
|
||||||
|
->setCellValue('A3', 7)
|
||||||
|
->setCellValue('B3', 8)
|
||||||
|
->setCellValue('C3', 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerRangeEvaluation
|
||||||
|
*
|
||||||
|
* @param mixed $formula
|
||||||
|
* @param int $expectedResult
|
||||||
|
*/
|
||||||
|
public function testRangeEvaluation($formula, $expectedResult): void
|
||||||
|
{
|
||||||
|
$workSheet = $this->spreadSheet->getActiveSheet();
|
||||||
|
$workSheet->setCellValue('E1', $formula);
|
||||||
|
|
||||||
|
$actualRresult = $workSheet->getCell('E1')->getCalculatedValue();
|
||||||
|
self::assertSame($expectedResult, $actualRresult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerRangeEvaluation()
|
||||||
|
{
|
||||||
|
return[
|
||||||
|
['=SUM(A1:B3,A1:C2)', 48],
|
||||||
|
['=SUM(A1:B3 A1:C2)', 12],
|
||||||
|
['=SUM(A1:A3,C1:C3)', 30],
|
||||||
|
['=SUM(A1:A3 C1:C3)', Functions::null()],
|
||||||
|
['=SUM(A1:B2,B2:C3)', 40],
|
||||||
|
['=SUM(A1:B2 B2:C3)', 5],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,7 @@ class DefaultValueBinderTest extends TestCase
|
||||||
['#REF!'],
|
['#REF!'],
|
||||||
[new DateTime()],
|
[new DateTime()],
|
||||||
[new DateTimeImmutable()],
|
[new DateTimeImmutable()],
|
||||||
|
['123456\n'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,37 @@ EOF;
|
||||||
self::assertEquals($expected, $sheet->getCell('B3')->getValue());
|
self::assertEquals($expected, $sheet->getCell('B3')->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testLineBreakEscape(): void
|
||||||
|
{
|
||||||
|
$reader = new Csv();
|
||||||
|
$spreadsheet = $reader->load('tests/data/Reader/CSV/line_break_in_enclosure_with_escaped_quotes.csv');
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$expected = <<<EOF
|
||||||
|
This is a "test csv file"
|
||||||
|
with both "line breaks"
|
||||||
|
and "escaped
|
||||||
|
quotes" that breaks
|
||||||
|
the delimiters
|
||||||
|
EOF;
|
||||||
|
self::assertEquals($expected, $sheet->getCell('B3')->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUtf32LineBreakEscape(): void
|
||||||
|
{
|
||||||
|
$reader = new Csv();
|
||||||
|
$reader->setInputEncoding('UTF-32LE');
|
||||||
|
$spreadsheet = $reader->load('tests/data/Reader/CSV/line_break_escaped_32le.csv');
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$expected = <<<EOF
|
||||||
|
This is a "test csv file"
|
||||||
|
with both "line breaks"
|
||||||
|
and "escaped
|
||||||
|
quotes" that breaks
|
||||||
|
the delimiters
|
||||||
|
EOF;
|
||||||
|
self::assertEquals($expected, $sheet->getCell('B3')->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public function testSeparatorLine(): void
|
public function testSeparatorLine(): void
|
||||||
{
|
{
|
||||||
$reader = new Csv();
|
$reader = new Csv();
|
||||||
|
|
|
@ -11,14 +11,6 @@ use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class Xlsx2Test extends TestCase
|
class Xlsx2Test extends TestCase
|
||||||
{
|
{
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
$outfile = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
|
|
||||||
if (file_exists($outfile)) {
|
|
||||||
unlink($outfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testLoadXlsxConditionalFormatting2(): void
|
public function testLoadXlsxConditionalFormatting2(): void
|
||||||
{
|
{
|
||||||
// Make sure Conditionals are read correctly from existing file
|
// Make sure Conditionals are read correctly from existing file
|
||||||
|
@ -63,6 +55,7 @@ class Xlsx2Test extends TestCase
|
||||||
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
|
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
|
||||||
$writer->save($outfile);
|
$writer->save($outfile);
|
||||||
$spreadsheet = $reader->load($outfile);
|
$spreadsheet = $reader->load($outfile);
|
||||||
|
unlink($outfile);
|
||||||
$worksheet = $spreadsheet->getActiveSheet();
|
$worksheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
$conditionalStyle = $worksheet->getConditionalStyles('A2:A8');
|
$conditionalStyle = $worksheet->getConditionalStyles('A2:A8');
|
||||||
|
@ -110,6 +103,7 @@ class Xlsx2Test extends TestCase
|
||||||
$writer->save($outfile);
|
$writer->save($outfile);
|
||||||
$reader = IOFactory::createReader('Xlsx');
|
$reader = IOFactory::createReader('Xlsx');
|
||||||
$spreadsheet = $reader->load($outfile);
|
$spreadsheet = $reader->load($outfile);
|
||||||
|
unlink($outfile);
|
||||||
$worksheet = $spreadsheet->getActiveSheet();
|
$worksheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
$conditionalStyle = $worksheet->getConditionalStyles('A1:A6');
|
$conditionalStyle = $worksheet->getConditionalStyles('A1:A6');
|
||||||
|
|
|
@ -222,6 +222,7 @@ class XlsxTest extends TestCase
|
||||||
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel);
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel);
|
||||||
$writer->save($resultFilename);
|
$writer->save($resultFilename);
|
||||||
$excel = $reader->load($resultFilename);
|
$excel = $reader->load($resultFilename);
|
||||||
|
unlink($resultFilename);
|
||||||
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
||||||
self::assertNotNull($excel);
|
self::assertNotNull($excel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,22 @@ class CodePageTest extends TestCase
|
||||||
return require 'tests/data/Shared/CodePage.php';
|
return require 'tests/data/Shared/CodePage.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCoverage(): void
|
||||||
|
{
|
||||||
|
$covered = [];
|
||||||
|
$expected = CodePage::getEncodings();
|
||||||
|
foreach ($expected as $key => $val) {
|
||||||
|
$covered[$key] = 0;
|
||||||
|
}
|
||||||
|
$tests = $this->providerCodePage();
|
||||||
|
foreach ($tests as $test) {
|
||||||
|
$covered[$test[1]] = 1;
|
||||||
|
}
|
||||||
|
foreach ($covered as $key => $val) {
|
||||||
|
self::assertEquals(1, $val, "Codepage $key not tested");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function testNumberToNameWithInvalidCodePage(): void
|
public function testNumberToNameWithInvalidCodePage(): void
|
||||||
{
|
{
|
||||||
$invalidCodePage = 12345;
|
$invalidCodePage = 12345;
|
||||||
|
|
|
@ -3,10 +3,23 @@
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Shared;
|
namespace PhpOffice\PhpSpreadsheetTests\Shared;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class DateTest extends TestCase
|
class DateTest extends TestCase
|
||||||
{
|
{
|
||||||
|
private $dttimezone;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->dttimezone = Date::getDefaultTimeZone();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Date::setDefaultTimeZone($this->dttimezone);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetExcelCalendar(): void
|
public function testSetExcelCalendar(): void
|
||||||
{
|
{
|
||||||
$calendarValues = [
|
$calendarValues = [
|
||||||
|
@ -168,4 +181,41 @@ class DateTest extends TestCase
|
||||||
{
|
{
|
||||||
return require 'tests/data/Shared/Date/ExcelToTimestamp1900Timezone.php';
|
return require 'tests/data/Shared/Date/ExcelToTimestamp1900Timezone.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testVarious(): void
|
||||||
|
{
|
||||||
|
Date::setDefaultTimeZone('UTC');
|
||||||
|
self::assertFalse(Date::stringToExcel('2019-02-29'));
|
||||||
|
self::assertTrue((bool) Date::stringToExcel('2019-02-28'));
|
||||||
|
self::assertTrue((bool) Date::stringToExcel('2019-02-28 11:18'));
|
||||||
|
self::assertFalse(Date::stringToExcel('2019-02-28 11:71'));
|
||||||
|
$date = Date::PHPToExcel('2020-01-01');
|
||||||
|
self::assertEquals(43831.0, $date);
|
||||||
|
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$sheet->setCellValue('B1', 'x');
|
||||||
|
$val = $sheet->getCell('B1')->getValue();
|
||||||
|
self::assertFalse(Date::timestampToExcel($val));
|
||||||
|
$cell = $sheet->getCell('A1');
|
||||||
|
self::assertNotNull($cell);
|
||||||
|
$cell->setValue($date);
|
||||||
|
$sheet->getStyle('A1')
|
||||||
|
->getNumberFormat()
|
||||||
|
->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME);
|
||||||
|
self::assertTrue(null !== $cell && Date::isDateTime($cell));
|
||||||
|
$cella2 = $sheet->getCell('A2');
|
||||||
|
self::assertNotNull($cella2);
|
||||||
|
$cella2->setValue('=A1+2');
|
||||||
|
$sheet->getStyle('A2')
|
||||||
|
->getNumberFormat()
|
||||||
|
->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME);
|
||||||
|
self::assertTrue(null !== $cella2 && Date::isDateTime($cella2));
|
||||||
|
$cella3 = $sheet->getCell('A3');
|
||||||
|
self::assertNotNull($cella3);
|
||||||
|
$cella3->setValue('=A1+4');
|
||||||
|
$sheet->getStyle('A3')
|
||||||
|
->getNumberFormat()
|
||||||
|
->setFormatCode('0.00E+00');
|
||||||
|
self::assertFalse(null !== $cella3 && Date::isDateTime($cella3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,29 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpSpreadsheetTests\Shared;
|
namespace PhpOffice\PhpSpreadsheetTests\Shared;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||||
use PhpOffice\PhpSpreadsheet\Shared\TimeZone;
|
use PhpOffice\PhpSpreadsheet\Shared\TimeZone;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class TimeZoneTest extends TestCase
|
class TimeZoneTest extends TestCase
|
||||||
{
|
{
|
||||||
|
private $tztimezone;
|
||||||
|
|
||||||
|
private $dttimezone;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->tztimezone = TimeZone::getTimeZone();
|
||||||
|
$this->dttimezone = Date::getDefaultTimeZone();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
TimeZone::setTimeZone($this->tztimezone);
|
||||||
|
Date::setDefaultTimeZone($this->dttimezone);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetTimezone(): void
|
public function testSetTimezone(): void
|
||||||
{
|
{
|
||||||
$timezoneValues = [
|
$timezoneValues = [
|
||||||
|
@ -20,13 +38,51 @@ class TimeZoneTest extends TestCase
|
||||||
foreach ($timezoneValues as $timezoneValue) {
|
foreach ($timezoneValues as $timezoneValue) {
|
||||||
$result = TimeZone::setTimezone($timezoneValue);
|
$result = TimeZone::setTimezone($timezoneValue);
|
||||||
self::assertTrue($result);
|
self::assertTrue($result);
|
||||||
|
$result = Date::setDefaultTimezone($timezoneValue);
|
||||||
|
self::assertTrue($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetTimezoneBackwardCompatible(): void
|
||||||
|
{
|
||||||
|
$bcTimezone = 'Etc/GMT+10';
|
||||||
|
$result = TimeZone::setTimezone($bcTimezone);
|
||||||
|
self::assertTrue($result);
|
||||||
|
$result = Date::setDefaultTimezone($bcTimezone);
|
||||||
|
self::assertTrue($result);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetTimezoneWithInvalidValue(): void
|
public function testSetTimezoneWithInvalidValue(): void
|
||||||
{
|
{
|
||||||
$unsupportedTimezone = 'Etc/GMT+10';
|
$unsupportedTimezone = 'XEtc/GMT+10';
|
||||||
$result = TimeZone::setTimezone($unsupportedTimezone);
|
$result = TimeZone::setTimezone($unsupportedTimezone);
|
||||||
self::assertFalse($result);
|
self::assertFalse($result);
|
||||||
|
$result = Date::setDefaultTimezone($unsupportedTimezone);
|
||||||
|
self::assertFalse($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTimeZoneAdjustmentsInvalidTz(): void
|
||||||
|
{
|
||||||
|
$this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
|
||||||
|
$dtobj = DateTime::createFromFormat('Y-m-d H:i:s', '2008-09-22 00:00:00');
|
||||||
|
$tstmp = $dtobj->getTimestamp();
|
||||||
|
$unsupportedTimeZone = 'XEtc/GMT+10';
|
||||||
|
TimeZone::getTimeZoneAdjustment($unsupportedTimeZone, $tstmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTimeZoneAdjustments(): void
|
||||||
|
{
|
||||||
|
$dtobj = DateTime::createFromFormat('Y-m-d H:i:s', '2008-01-01 00:00:00');
|
||||||
|
$tstmp = $dtobj->getTimestamp();
|
||||||
|
$supportedTimeZone = 'UTC';
|
||||||
|
$adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
|
||||||
|
self::assertEquals(0, $adj);
|
||||||
|
$supportedTimeZone = 'America/Toronto';
|
||||||
|
$adj = TimeZone::getTimeZoneAdjustment($supportedTimeZone, $tstmp);
|
||||||
|
self::assertEquals(-18000, $adj);
|
||||||
|
$supportedTimeZone = 'America/Chicago';
|
||||||
|
TimeZone::setTimeZone($supportedTimeZone);
|
||||||
|
$adj = TimeZone::getTimeZoneAdjustment(null, $tstmp);
|
||||||
|
self::assertEquals(-21600, $adj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,18 @@ use PhpOffice\PhpSpreadsheetTests\Functional;
|
||||||
|
|
||||||
class ImagesRootTest extends Functional\AbstractFunctional
|
class ImagesRootTest extends Functional\AbstractFunctional
|
||||||
{
|
{
|
||||||
|
private $curdir;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->curdir = getcwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
chdir($this->curdir);
|
||||||
|
}
|
||||||
|
|
||||||
public function testImagesRoot(): void
|
public function testImagesRoot(): void
|
||||||
{
|
{
|
||||||
$spreadsheet = new Spreadsheet();
|
$spreadsheet = new Spreadsheet();
|
||||||
|
@ -20,7 +32,6 @@ class ImagesRootTest extends Functional\AbstractFunctional
|
||||||
$newdir = __DIR__ . '/../../../data/Reader/HTML';
|
$newdir = __DIR__ . '/../../../data/Reader/HTML';
|
||||||
$stub = 'image.jpg';
|
$stub = 'image.jpg';
|
||||||
$imagePath = "./$stub";
|
$imagePath = "./$stub";
|
||||||
$curdir = getcwd();
|
|
||||||
chdir($newdir);
|
chdir($newdir);
|
||||||
self::assertFileExists($imagePath);
|
self::assertFileExists($imagePath);
|
||||||
$drawing->setPath($imagePath);
|
$drawing->setPath($imagePath);
|
||||||
|
@ -34,7 +45,6 @@ class ImagesRootTest extends Functional\AbstractFunctional
|
||||||
$writer = new Html($spreadsheet);
|
$writer = new Html($spreadsheet);
|
||||||
$writer->setImagesRoot($root);
|
$writer->setImagesRoot($root);
|
||||||
$html = $writer->generateHTMLAll();
|
$html = $writer->generateHTMLAll();
|
||||||
chdir($curdir);
|
|
||||||
$dom = new DOMDocument();
|
$dom = new DOMDocument();
|
||||||
$dom->loadHTML($html);
|
$dom->loadHTML($html);
|
||||||
$body = $dom->getElementsByTagName('body')[0];
|
$body = $dom->getElementsByTagName('body')[0];
|
||||||
|
|
|
@ -30,9 +30,8 @@ class InvalidFileNameTest extends Functional\AbstractFunctional
|
||||||
$writer->save('');
|
$writer->save('');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEmptyTempdirNamePdf(): void
|
public function testNotEmptyTempdirNamePdf(): void
|
||||||
{
|
{
|
||||||
$this->expectException(WriterException::class);
|
|
||||||
$spreadsheet = new Spreadsheet();
|
$spreadsheet = new Spreadsheet();
|
||||||
$spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1');
|
$spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1');
|
||||||
$writer = new Mpdf($spreadsheet);
|
$writer = new Mpdf($spreadsheet);
|
||||||
|
@ -41,6 +40,16 @@ class InvalidFileNameTest extends Functional\AbstractFunctional
|
||||||
$writer->setPaperSize(PageSetup::PAPERSIZE_LEDGER);
|
$writer->setPaperSize(PageSetup::PAPERSIZE_LEDGER);
|
||||||
self::assertEquals($writer->getPaperSize(), PageSetup::PAPERSIZE_LEDGER);
|
self::assertEquals($writer->getPaperSize(), PageSetup::PAPERSIZE_LEDGER);
|
||||||
self::assertEquals(File::sysGetTempDir() . '/phpsppdf', $writer->getTempDir());
|
self::assertEquals(File::sysGetTempDir() . '/phpsppdf', $writer->getTempDir());
|
||||||
|
$writer->setTempDir(File::sysGetTempDir());
|
||||||
|
self::assertEquals(File::sysGetTempDir(), $writer->getTempDir());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyTempdirNamePdf(): void
|
||||||
|
{
|
||||||
|
$this->expectException(WriterException::class);
|
||||||
|
$spreadsheet = new Spreadsheet();
|
||||||
|
$spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1');
|
||||||
|
$writer = new Mpdf($spreadsheet);
|
||||||
$writer->setTempDir('');
|
$writer->setTempDir('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,6 @@ use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class FormulaErrTest extends TestCase
|
class FormulaErrTest extends TestCase
|
||||||
{
|
{
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
|
|
||||||
if (file_exists($filename)) {
|
|
||||||
unlink($filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testFormulaError(): void
|
public function testFormulaError(): void
|
||||||
{
|
{
|
||||||
$obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
$obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||||
|
@ -31,6 +23,7 @@ class FormulaErrTest extends TestCase
|
||||||
$writer->save($filename);
|
$writer->save($filename);
|
||||||
$reader = IOFactory::createReader('Xls');
|
$reader = IOFactory::createReader('Xls');
|
||||||
$robj = $reader->load($filename);
|
$robj = $reader->load($filename);
|
||||||
|
unlink($filename);
|
||||||
$sheet0 = $robj->setActiveSheetIndex(0);
|
$sheet0 = $robj->setActiveSheetIndex(0);
|
||||||
$a1 = $sheet0->getCell('A1')->getCalculatedValue();
|
$a1 = $sheet0->getCell('A1')->getCalculatedValue();
|
||||||
self::assertEquals(2, $a1);
|
self::assertEquals(2, $a1);
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xlsx;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Settings;
|
||||||
|
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||||
|
|
||||||
|
class DrawingsTest extends AbstractFunctional
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $prevValue;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->prevValue = Settings::getLibXmlLoaderOptions();
|
||||||
|
|
||||||
|
// Disable validating XML with the DTD
|
||||||
|
Settings::setLibXmlLoaderOptions($this->prevValue & ~LIBXML_DTDVALID & ~LIBXML_DTDATTR & ~LIBXML_DTDLOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
Settings::setLibXmlLoaderOptions($this->prevValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test save and load XLSX file with drawing on 2nd worksheet.
|
||||||
|
*/
|
||||||
|
public function testSaveLoadWithDrawingOn2ndWorksheet(): void
|
||||||
|
{
|
||||||
|
// Read spreadsheet from file
|
||||||
|
$inputFilename = 'tests/data/Writer/XLSX/drawing_on_2nd_page.xlsx';
|
||||||
|
$reader = new Xlsx();
|
||||||
|
$spreadsheet = $reader->load($inputFilename);
|
||||||
|
|
||||||
|
// Save spreadsheet to file and read it back
|
||||||
|
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
|
||||||
|
|
||||||
|
// Fake assert. The only thing we need is to ensure the file is loaded without exception
|
||||||
|
self::assertNotNull($reloadedSpreadsheet);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ class FloatsRetainedTest extends TestCase
|
||||||
|
|
||||||
$reader = new Reader();
|
$reader = new Reader();
|
||||||
$sheet = $reader->load($outputFilename);
|
$sheet = $reader->load($outputFilename);
|
||||||
|
unlink($outputFilename);
|
||||||
|
|
||||||
self::assertSame($value, $sheet->getActiveSheet()->getCell('A1')->getValue());
|
self::assertSame($value, $sheet->getActiveSheet()->getCell('A1')->getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,4 +73,8 @@ return [
|
||||||
'e',
|
'e',
|
||||||
'#DIV/0!',
|
'#DIV/0!',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
's',
|
||||||
|
'123456\n',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
Binary file not shown.
Can't render this file because it contains an unexpected character in line 2 and column 24.
|
|
@ -1,21 +1,21 @@
|
||||||
Name,Copy,URL
|
Name,Copy,URL
|
||||||
Test,"This is a \"test csv file\"
|
Test,"This is a ""test csv file""
|
||||||
with both \"line breaks\"
|
with both ""line breaks""
|
||||||
and \"escaped
|
and ""escaped
|
||||||
quotes\" that breaks
|
quotes"" that breaks
|
||||||
the delimiters",http://google.com
|
the delimiters",http://google.com
|
||||||
Test,"This is a \"test csv file\"
|
Test,"This is a ""test csv file""
|
||||||
with both \"line breaks\"
|
with both ""line breaks""
|
||||||
and \"escaped
|
and ""escaped
|
||||||
quotes\" that breaks
|
quotes"" that breaks
|
||||||
the delimiters",http://google.com
|
the delimiters",http://google.com
|
||||||
Test,"This is a \"test csv file\"
|
Test,"This is a ""test csv file""
|
||||||
with both \"line breaks\"
|
with both ""line breaks""
|
||||||
and \"escaped
|
and ""escaped
|
||||||
quotes\" that breaks
|
quotes"" that breaks
|
||||||
the delimiters",http://google.com
|
the delimiters",http://google.com
|
||||||
Test,"This is a \"test csv file\"
|
Test,"This is a ""test csv file""
|
||||||
with both \"line breaks\"
|
with both ""line breaks""
|
||||||
and \"escaped
|
and ""escaped
|
||||||
quotes\" that breaks
|
quotes"" that breaks
|
||||||
the delimiters",http://google.com
|
the delimiters",http://google.com
|
||||||
|
|
Can't render this file because it contains an unexpected character in line 2 and column 18.
|
|
@ -1,6 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
// ANSI Latin I (BIFF4-BIFF7)
|
||||||
|
[
|
||||||
|
'CP1252',
|
||||||
|
0,
|
||||||
|
],
|
||||||
// ASCII
|
// ASCII
|
||||||
[
|
[
|
||||||
'ASCII',
|
'ASCII',
|
||||||
|
@ -127,11 +132,6 @@ return [
|
||||||
1251,
|
1251,
|
||||||
],
|
],
|
||||||
// ANSI Latin I (BIFF4-BIFF7)
|
// ANSI Latin I (BIFF4-BIFF7)
|
||||||
[
|
|
||||||
'CP1252',
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
// ANSI Latin I (BIFF4-BIFF7)
|
|
||||||
[
|
[
|
||||||
'CP1252',
|
'CP1252',
|
||||||
1252,
|
1252,
|
||||||
|
@ -176,6 +176,31 @@ return [
|
||||||
'MAC',
|
'MAC',
|
||||||
10000,
|
10000,
|
||||||
],
|
],
|
||||||
|
// Macintosh Japanese
|
||||||
|
[
|
||||||
|
'CP932',
|
||||||
|
10001,
|
||||||
|
],
|
||||||
|
// Macintosh Chinese Traditional
|
||||||
|
[
|
||||||
|
'CP950',
|
||||||
|
10002,
|
||||||
|
],
|
||||||
|
// Macintosh Korean
|
||||||
|
[
|
||||||
|
'CP1361',
|
||||||
|
10003,
|
||||||
|
],
|
||||||
|
// Apple Arabic
|
||||||
|
[
|
||||||
|
'MACARABIC',
|
||||||
|
10004,
|
||||||
|
],
|
||||||
|
// Apple Hebrew
|
||||||
|
[
|
||||||
|
'MACHEBREW',
|
||||||
|
10005,
|
||||||
|
],
|
||||||
// Macintosh Greek
|
// Macintosh Greek
|
||||||
[
|
[
|
||||||
'MACGREEK',
|
'MACGREEK',
|
||||||
|
@ -186,6 +211,26 @@ return [
|
||||||
'MACCYRILLIC',
|
'MACCYRILLIC',
|
||||||
10007,
|
10007,
|
||||||
],
|
],
|
||||||
|
// Macintosh - Simplified Chinese (GB 2312)
|
||||||
|
[
|
||||||
|
'CP936',
|
||||||
|
10008,
|
||||||
|
],
|
||||||
|
// Macintosh Romania
|
||||||
|
[
|
||||||
|
'MACROMANIA',
|
||||||
|
10010,
|
||||||
|
],
|
||||||
|
// Macintosh Ukraine
|
||||||
|
[
|
||||||
|
'MACUKRAINE',
|
||||||
|
10017,
|
||||||
|
],
|
||||||
|
// Macintosh Thai
|
||||||
|
[
|
||||||
|
'MACTHAI',
|
||||||
|
10021,
|
||||||
|
],
|
||||||
// Macintosh Central Europe
|
// Macintosh Central Europe
|
||||||
[
|
[
|
||||||
'MACCENTRALEUROPE',
|
'MACCENTRALEUROPE',
|
||||||
|
@ -201,6 +246,16 @@ return [
|
||||||
'MACTURKISH',
|
'MACTURKISH',
|
||||||
10081,
|
10081,
|
||||||
],
|
],
|
||||||
|
// Macintosh Croatian
|
||||||
|
[
|
||||||
|
'MACCROATIAN',
|
||||||
|
10082,
|
||||||
|
],
|
||||||
|
// UTF-16 (BIFF8) grandfathers erroneous libraries
|
||||||
|
[
|
||||||
|
'UTF-16LE',
|
||||||
|
21010,
|
||||||
|
],
|
||||||
// Apple Roman
|
// Apple Roman
|
||||||
[
|
[
|
||||||
'MAC',
|
'MAC',
|
||||||
|
|
|
@ -146,4 +146,8 @@ return [
|
||||||
false,
|
false,
|
||||||
'#,##0.00 "dollars"',
|
'#,##0.00 "dollars"',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
true,
|
||||||
|
'"date " y-m-d',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue