Merge pull request #3 from PHPOffice/master

Sync Up With Base
This commit is contained in:
oleibman 2020-05-24 22:51:25 -07:00 committed by GitHub
commit 79d024fec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 545 additions and 226 deletions

View File

@ -18,7 +18,7 @@ build:
tools:
external_code_coverage:
timeout: 3600
timeout: 600
build_failure_conditions:
- 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed

View File

@ -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)
- 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)
- 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

View File

@ -17,3 +17,4 @@ $helper->logRead('Xlsx', $filename, $callStartTime);
// Save
$helper->write($spreadsheet, __FILE__);
unlink($filename);

View File

@ -1,13 +1,15 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Csv as CsvReader;
use PhpOffice\PhpSpreadsheet\Writer\Csv as CsvWriter;
require __DIR__ . '/../Header.php';
$spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
$helper->log('Write to CSV format');
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writer */
$writer = IOFactory::createWriter($spreadsheet, 'Csv')->setDelimiter(',')
$writer = new CsvWriter($spreadsheet);
$writer->setDelimiter(',')
->setEnclosure('"')
->setSheetIndex(0);
@ -19,13 +21,15 @@ $helper->logWrite($writer, $filename, $callStartTime);
$helper->log('Read from CSV format');
/** @var \PhpOffice\PhpSpreadsheet\Reader\Csv $reader */
$reader = IOFactory::createReader('Csv')->setDelimiter(',')
$reader = new CsvReader();
$reader->setDelimiter(',')
->setEnclosure('"')
->setSheetIndex(0);
$callStartTime = microtime(true);
$spreadsheetFromCSV = $reader->load($filename);
$helper->logRead('Csv', $filename, $callStartTime);
unlink($filename);
// Write Xlsx
$helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
@ -33,7 +37,7 @@ $helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']);
// Write CSV
$filenameCSV = $helper->getFilename(__FILE__, 'csv');
/** @var \PhpOffice\PhpSpreadsheet\Writer\Csv $writerCSV */
$writerCSV = IOFactory::createWriter($spreadsheetFromCSV, 'Csv');
$writerCSV = new CsvWriter($spreadsheetFromCSV);
$writerCSV->setExcelCompatibility(true);
$callStartTime = microtime(true);

View File

@ -17,6 +17,7 @@ $helper->logWrite($writer, $filename, $callStartTime);
$callStartTime = microtime(true);
$spreadsheet = IOFactory::load($filename);
$helper->logRead('Xls', $filename, $callStartTime);
unlink($filename);
// Save
$helper->write($spreadsheet, __FILE__);

View File

@ -3,6 +3,7 @@
namespace PhpOffice\PhpSpreadsheet;
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
require __DIR__ . '/../Header.php';
@ -29,10 +30,11 @@ class MyReadFilter implements IReadFilter
}
$helper->log('Load from Xlsx file');
$reader = IOFactory::createReader('Xlsx');
$reader = new XlsxReader();
$reader->setReadFilter(new MyReadFilter());
$callStartTime = microtime(true);
$spreadsheet = $reader->load($filename);
unlink($filename);
$helper->logRead('Xlsx', $filename, $callStartTime);
$helper->log('Remove unnecessary rows');
$spreadsheet->getActiveSheet()->removeRow(2, 18);

View File

@ -1,21 +1,22 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XLsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XLsxWriter;
require __DIR__ . '/../Header.php';
$sampleSpreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php';
$filename = $helper->getTemporaryFilename();
$writer = new Xlsx($sampleSpreadsheet);
$writer = new XlsxWriter($sampleSpreadsheet);
$callStartTime = microtime(true);
$writer->save($filename);
$helper->logWrite($writer, $filename, $callStartTime);
$callStartTime = microtime(true);
$reader = IOFactory::createReader('Xlsx');
$reader = new XlsxReader();
$spreadsheet = $reader->load($filename);
$helper->logRead('Xlsx', $filename, $callStartTime);
unlink($filename);
$helper->log('Iterate worksheets');
foreach ($spreadsheet->getWorksheetIterator() as $worksheet) {
$helper->log('Worksheet - ' . $worksheet->getTitle());

View File

@ -24,3 +24,5 @@ var_dump($sheetList);
$helper->log('Worksheet Names:');
var_dump($sheetInfo);
unlink($filename);

View File

@ -1,20 +1,22 @@
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
require __DIR__ . '/../Header.php';
// Create temporary file that will be read
$sampleSpreadsheet = require __DIR__ . '/../templates/chartSpreadsheet.php';
$filename = $helper->getTemporaryFilename();
$writer = new Xlsx($sampleSpreadsheet);
$writer = new XlsxWriter($sampleSpreadsheet);
$writer->setIncludeCharts(true);
$writer->save($filename);
$helper->log('Load from Xlsx file');
$reader = IOFactory::createReader('Xlsx');
$reader = new XlsxReader();
$reader->setIncludeCharts(true);
$spreadsheet = $reader->load($filename);
unlink($filename);
$helper->log('Update cell data values that are displayed in the chart');
$worksheet = $spreadsheet->getActiveSheet();
@ -31,7 +33,7 @@ $worksheet->fromArray(
// Save Excel 2007 file
$filename = $helper->getFilename(__FILE__);
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer = new XlsxWriter($spreadsheet);
$writer->setIncludeCharts(true);
$callStartTime = microtime(true);
$writer->save($filename);

View File

@ -37,6 +37,10 @@ class Calculation
const RETURN_ARRAY_AS_VALUE = 'value';
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;
/**
@ -2593,11 +2597,11 @@ class Calculation
for ($i = 0; $i < $strlen; ++$i) {
$chr = mb_substr($formula, $i, 1);
switch ($chr) {
case '{':
case self::FORMULA_OPEN_FUNCTION_BRACE:
$inBraces = true;
break;
case '}':
case self::FORMULA_CLOSE_FUNCTION_BRACE:
$inBraces = false;
break;
@ -2626,10 +2630,10 @@ class Calculation
if (self::$localeLanguage !== 'en_us') {
$inBraces = false;
// 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
// the formula
$temp = explode('"', $formula);
$temp = explode(self::FORMULA_STRING_QUOTE, $formula);
$i = false;
foreach ($temp as &$value) {
// Only count/replace in alternating array entries
@ -2640,7 +2644,7 @@ class Calculation
}
unset($value);
// Then rebuild the formula string
$formula = implode('"', $temp);
$formula = implode(self::FORMULA_STRING_QUOTE, $temp);
} else {
// If there's no quoted strings, then we do a simple count/replace
$formula = preg_replace($from, $to, $formula);
@ -2741,7 +2745,7 @@ class Calculation
return $value;
}
// Return strings wrapped in quotes
return '"' . $value . '"';
return self::FORMULA_STRING_QUOTE . $value . self::FORMULA_STRING_QUOTE;
// Convert numeric errors to NaN error
} elseif ((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) {
return Functions::NAN();
@ -2760,7 +2764,7 @@ class Calculation
public static function unwrapResult($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);
}
// Convert numeric errors to NAN error
@ -3227,8 +3231,8 @@ class Calculation
}
return '{ ' . implode($rpad, $returnMatrix) . ' }';
} elseif (is_string($value) && (trim($value, '"') == $value)) {
return '"' . $value . '"';
} elseif (is_string($value) && (trim($value, self::FORMULA_STRING_QUOTE) == $value)) {
return self::FORMULA_STRING_QUOTE . $value . self::FORMULA_STRING_QUOTE;
} elseif (is_bool($value)) {
return ($value) ? self::$localeBoolean['TRUE'] : self::$localeBoolean['FALSE'];
}
@ -3282,34 +3286,34 @@ class Calculation
*/
private function convertMatrixReferences($formula)
{
static $matrixReplaceFrom = ['{', ';', '}'];
static $matrixReplaceFrom = [self::FORMULA_OPEN_FUNCTION_BRACE, ';', self::FORMULA_CLOSE_FUNCTION_BRACE];
static $matrixReplaceTo = ['MKMATRIX(MKMATRIX(', '),MKMATRIX(', '))'];
// 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 (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
// the formula
$temp = explode('"', $formula);
$temp = explode(self::FORMULA_STRING_QUOTE, $formula);
// Open and Closed counts used for trapping mismatched braces in the formula
$openCount = $closeCount = 0;
$i = false;
foreach ($temp as &$value) {
// Only count/replace in alternating array entries
if ($i = !$i) {
$openCount += substr_count($value, '{');
$closeCount += substr_count($value, '}');
$openCount += substr_count($value, self::FORMULA_OPEN_FUNCTION_BRACE);
$closeCount += substr_count($value, self::FORMULA_CLOSE_FUNCTION_BRACE);
$value = str_replace($matrixReplaceFrom, $matrixReplaceTo, $value);
}
}
unset($value);
// Then rebuild the formula string
$formula = implode('"', $temp);
$formula = implode(self::FORMULA_STRING_QUOTE, $temp);
} else {
// If there's no quoted strings, then we do a simple count/replace
$openCount = substr_count($formula, '{');
$closeCount = substr_count($formula, '}');
$openCount = substr_count($formula, self::FORMULA_OPEN_FUNCTION_BRACE);
$closeCount = substr_count($formula, self::FORMULA_CLOSE_FUNCTION_BRACE);
$formula = str_replace($matrixReplaceFrom, $matrixReplaceTo, $formula);
}
// Trap for mismatched braces and trigger an appropriate error
@ -3715,9 +3719,9 @@ class Calculation
}
$localeConstant = false;
if ($opCharacter == '"') {
if ($opCharacter == self::FORMULA_STRING_QUOTE) {
// 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)) {
if ((strpos($val, '.') !== false) || (stripos($val, 'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) {
$val = (float) $val;
@ -4058,7 +4062,7 @@ class Calculation
$result = '#VALUE!';
}
} 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));
$stack->push('Value', $result);
@ -4078,9 +4082,15 @@ class Calculation
$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));
$stack->push('Value', $cellIntersect, $cellRef);
}
break;
}
@ -4284,7 +4294,7 @@ class Calculation
$branchStore[$storeKey] = 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);
if (isset($storeKey)) {
$branchStore[$storeKey] = $token;
@ -4329,7 +4339,7 @@ class Calculation
if (is_string($operand)) {
// 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
if ($operand > '' && $operand[0] == '"') {
if ($operand > '' && $operand[0] == self::FORMULA_STRING_QUOTE) {
$operand = self::unwrapResult($operand);
}
// 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;
} 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
$stack->push('Value', '#VALUE!');
$stack->push('Error', '#VALUE!');
$this->debugLog->writeDebugLog('Evaluation Result is a ', $this->showTypeDetails('#VALUE!'));
return false;
@ -4402,10 +4412,10 @@ class Calculation
}
// 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);
}
if (is_string($operand2) && $operand2 > '' && $operand2[0] == '"') {
if (is_string($operand2) && $operand2 > '' && $operand2[0] == self::FORMULA_STRING_QUOTE) {
$operand2 = self::unwrapResult($operand2);
}
@ -4570,7 +4580,7 @@ class Calculation
case '/':
if ($operand2 == 0) {
// 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!'));
return false;

View File

@ -1339,6 +1339,8 @@ class MathTrig
// Is it a numeric value?
if ((is_numeric($arg)) && (!is_string($arg))) {
$returnValue += $arg;
} elseif (Functions::isError($arg)) {
return $arg;
}
}

View File

@ -65,6 +65,8 @@ class DefaultValueBinder implements IValueBinder
return DataType::TYPE_STRING;
} elseif ((strpos($pValue, '.') === false) && ($pValue > PHP_INT_MAX)) {
return DataType::TYPE_STRING;
} elseif (!is_numeric($pValue)) {
return DataType::TYPE_STRING;
}
return DataType::TYPE_NUMERIC;

View File

@ -933,7 +933,12 @@ class Html extends BaseReader
*/
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);
}
$cellStyle->applyFromArray([
'borders' => [

View File

@ -1000,12 +1000,13 @@ class Xlsx extends BaseReader
Settings::getLibXmlLoaderOptions()
);
$drawings = [];
if (isset($relsVML->Relationship)) {
foreach ($relsVML->Relationship as $ele) {
if ($ele['Type'] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') {
$drawings[(string) $ele['Id']] = self::dirAdd($vmlRelationship, $ele['Target']);
}
}
}
// Fetch VML document
$vmlDrawing = simplexml_load_string(
$this->securityScanner->scan($this->getFromZipArchive($zip, $vmlRelationship)),

View File

@ -6,6 +6,65 @@ use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
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
* and mbstring understands.
@ -14,123 +73,20 @@ class CodePage
*
* @return string Code Page Name
*/
public static function numberToName($codePage)
public static function numberToName(int $codePage): string
{
switch ($codePage) {
case 367:
return 'ASCII'; // ASCII
case 437:
return 'CP437'; // OEM US
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)
if (array_key_exists($codePage, self::$pageArray)) {
return self::$pageArray[$codePage];
}
if ($codePage == 720 || $codePage == 32769) {
throw new PhpSpreadsheetException("Code page $codePage not supported."); // OEM Arabic
}
throw new PhpSpreadsheetException('Unknown codepage: ' . $codePage);
}
public static function getEncodings(): array
{
return self::$pageArray;
}
}

View File

@ -4,10 +4,10 @@ namespace PhpOffice\PhpSpreadsheet\Shared;
use DateTimeInterface;
use DateTimeZone;
use Exception;
use PhpOffice\PhpSpreadsheet\Calculation\DateTime;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
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
*
* @return bool Success or failure
* @return bool Success or failure
*/
public static function setDefaultTimezone($timeZone)
{
if ($timeZone = self::validateTimeZone($timeZone)) {
try {
$timeZone = self::validateTimeZone($timeZone);
self::$defaultTimeZone = $timeZone;
return true;
$retval = 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
*
* @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;
} elseif (is_string($timeZone)) {
}
if (in_array($timeZone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC))) {
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)
{
return is_numeric($pCell->getValue()) &&
return is_numeric($pCell->getCalculatedValue()) &&
self::isDateTimeFormat(
$pCell->getWorksheet()->getStyle(
$pCell->getCoordinate()

View File

@ -23,7 +23,7 @@ class 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;
}
if ($timezone == 'UST') {
return 0;
}
$objTimezone = new DateTimeZone($timezone);
$transitions = $objTimezone->getTransitions($timestamp, $timestamp);

View File

@ -183,7 +183,6 @@ class Rels extends WriterPart
$objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships');
// Write drawing relationships?
$d = 0;
$drawingOriginalIds = [];
$unparsedLoadedData = $pWorksheet->getParent()->getUnparsedLoadedData();
if (isset($unparsedLoadedData['sheets'][$pWorksheet->getCodeName()]['drawingOriginalIds'])) {
@ -197,13 +196,19 @@ class Rels extends WriterPart
}
if (($pWorksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
$relPath = '../drawings/drawing' . $pWorksheetId . '.xml';
$rId = ++$d;
$rId = 1;
// 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])) {
$rId = (int) (substr($drawingOriginalIds[$relPath], 3));
}
// Generate new $relPath to write drawing relationship
$relPath = '../drawings/drawing' . $pWorksheetId . '.xml';
$this->writeRelationship(
$objWriter,
$rId,

View File

@ -1215,6 +1215,7 @@ class Worksheet extends WriterPart
if (isset($unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'])) {
$drawingOriginalIds = $unparsedLoadedData['sheets'][$pSheet->getCodeName()]['drawingOriginalIds'];
// take first. In future can be overriten
// (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels::writeWorksheetRelationships)
$rId = reset($drawingOriginalIds);
}

View File

@ -18,5 +18,6 @@ class DefinedNameConfusedForCellTest extends TestCase
$filename = tempnam(File::sysGetTempDir(), 'phpspreadsheet-test');
$writer->save($filename);
self::assertTrue(true);
unlink($filename);
}
}

View File

@ -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],
];
}
}

View File

@ -57,6 +57,7 @@ class DefaultValueBinderTest extends TestCase
['#REF!'],
[new DateTime()],
[new DateTimeImmutable()],
['123456\n'],
];
}

View File

@ -200,6 +200,37 @@ EOF;
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
{
$reader = new Csv();

View File

@ -11,14 +11,6 @@ use PHPUnit\Framework\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
{
// Make sure Conditionals are read correctly from existing file
@ -63,6 +55,7 @@ class Xlsx2Test extends TestCase
$writer = IOFactory::createWriter($spreadshee1, 'Xlsx');
$writer->save($outfile);
$spreadsheet = $reader->load($outfile);
unlink($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A2:A8');
@ -110,6 +103,7 @@ class Xlsx2Test extends TestCase
$writer->save($outfile);
$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($outfile);
unlink($outfile);
$worksheet = $spreadsheet->getActiveSheet();
$conditionalStyle = $worksheet->getConditionalStyles('A1:A6');

View File

@ -222,6 +222,7 @@ class XlsxTest extends TestCase
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($excel);
$writer->save($resultFilename);
$excel = $reader->load($resultFilename);
unlink($resultFilename);
// Fake assert. The only thing we need is to ensure the file is loaded without exception
self::assertNotNull($excel);
}

View File

@ -24,6 +24,22 @@ class CodePageTest extends TestCase
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
{
$invalidCodePage = 12345;

View File

@ -3,10 +3,23 @@
namespace PhpOffice\PhpSpreadsheetTests\Shared;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PHPUnit\Framework\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
{
$calendarValues = [
@ -168,4 +181,41 @@ class DateTest extends TestCase
{
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));
}
}

View File

@ -2,11 +2,29 @@
namespace PhpOffice\PhpSpreadsheetTests\Shared;
use DateTime;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Shared\TimeZone;
use PHPUnit\Framework\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
{
$timezoneValues = [
@ -20,13 +38,51 @@ class TimeZoneTest extends TestCase
foreach ($timezoneValues as $timezoneValue) {
$result = TimeZone::setTimezone($timezoneValue);
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
{
$unsupportedTimezone = 'Etc/GMT+10';
$unsupportedTimezone = 'XEtc/GMT+10';
$result = TimeZone::setTimezone($unsupportedTimezone);
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);
}
}

View File

@ -9,6 +9,18 @@ use PhpOffice\PhpSpreadsheetTests\Functional;
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
{
$spreadsheet = new Spreadsheet();
@ -20,7 +32,6 @@ class ImagesRootTest extends Functional\AbstractFunctional
$newdir = __DIR__ . '/../../../data/Reader/HTML';
$stub = 'image.jpg';
$imagePath = "./$stub";
$curdir = getcwd();
chdir($newdir);
self::assertFileExists($imagePath);
$drawing->setPath($imagePath);
@ -34,7 +45,6 @@ class ImagesRootTest extends Functional\AbstractFunctional
$writer = new Html($spreadsheet);
$writer->setImagesRoot($root);
$html = $writer->generateHTMLAll();
chdir($curdir);
$dom = new DOMDocument();
$dom->loadHTML($html);
$body = $dom->getElementsByTagName('body')[0];

View File

@ -30,9 +30,8 @@ class InvalidFileNameTest extends Functional\AbstractFunctional
$writer->save('');
}
public function testEmptyTempdirNamePdf(): void
public function testNotEmptyTempdirNamePdf(): void
{
$this->expectException(WriterException::class);
$spreadsheet = new Spreadsheet();
$spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1');
$writer = new Mpdf($spreadsheet);
@ -41,6 +40,16 @@ class InvalidFileNameTest extends Functional\AbstractFunctional
$writer->setPaperSize(PageSetup::PAPERSIZE_LEDGER);
self::assertEquals($writer->getPaperSize(), PageSetup::PAPERSIZE_LEDGER);
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('');
}

View File

@ -9,14 +9,6 @@ use PHPUnit\Framework\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
{
$obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
@ -31,6 +23,7 @@ class FormulaErrTest extends TestCase
$writer->save($filename);
$reader = IOFactory::createReader('Xls');
$robj = $reader->load($filename);
unlink($filename);
$sheet0 = $robj->setActiveSheetIndex(0);
$a1 = $sheet0->getCell('A1')->getCalculatedValue();
self::assertEquals(2, $a1);

View File

@ -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);
}
}

View File

@ -28,6 +28,7 @@ class FloatsRetainedTest extends TestCase
$reader = new Reader();
$sheet = $reader->load($outputFilename);
unlink($outputFilename);
self::assertSame($value, $sheet->getActiveSheet()->getCell('A1')->getValue());
}

View File

@ -73,4 +73,8 @@ return [
'e',
'#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.

View File

@ -1,21 +1,21 @@
Name,Copy,URL
Test,"This is a \"test csv file\"
with both \"line breaks\"
and \"escaped
quotes\" that breaks
Test,"This is a ""test csv file""
with both ""line breaks""
and ""escaped
quotes"" that breaks
the delimiters",http://google.com
Test,"This is a \"test csv file\"
with both \"line breaks\"
and \"escaped
quotes\" that breaks
Test,"This is a ""test csv file""
with both ""line breaks""
and ""escaped
quotes"" that breaks
the delimiters",http://google.com
Test,"This is a \"test csv file\"
with both \"line breaks\"
and \"escaped
quotes\" that breaks
Test,"This is a ""test csv file""
with both ""line breaks""
and ""escaped
quotes"" that breaks
the delimiters",http://google.com
Test,"This is a \"test csv file\"
with both \"line breaks\"
and \"escaped
quotes\" that breaks
Test,"This is a ""test csv file""
with both ""line breaks""
and ""escaped
quotes"" that breaks
the delimiters",http://google.com

Can't render this file because it contains an unexpected character in line 2 and column 18.

View File

@ -1,6 +1,11 @@
<?php
return [
// ANSI Latin I (BIFF4-BIFF7)
[
'CP1252',
0,
],
// ASCII
[
'ASCII',
@ -127,11 +132,6 @@ return [
1251,
],
// ANSI Latin I (BIFF4-BIFF7)
[
'CP1252',
0,
],
// ANSI Latin I (BIFF4-BIFF7)
[
'CP1252',
1252,
@ -176,6 +176,31 @@ return [
'MAC',
10000,
],
// Macintosh Japanese
[
'CP932',
10001,
],
// Macintosh Chinese Traditional
[
'CP950',
10002,
],
// Macintosh Korean
[
'CP1361',
10003,
],
// Apple Arabic
[
'MACARABIC',
10004,
],
// Apple Hebrew
[
'MACHEBREW',
10005,
],
// Macintosh Greek
[
'MACGREEK',
@ -186,6 +211,26 @@ return [
'MACCYRILLIC',
10007,
],
// Macintosh - Simplified Chinese (GB 2312)
[
'CP936',
10008,
],
// Macintosh Romania
[
'MACROMANIA',
10010,
],
// Macintosh Ukraine
[
'MACUKRAINE',
10017,
],
// Macintosh Thai
[
'MACTHAI',
10021,
],
// Macintosh Central Europe
[
'MACCENTRALEUROPE',
@ -201,6 +246,16 @@ return [
'MACTURKISH',
10081,
],
// Macintosh Croatian
[
'MACCROATIAN',
10082,
],
// UTF-16 (BIFF8) grandfathers erroneous libraries
[
'UTF-16LE',
21010,
],
// Apple Roman
[
'MAC',

View File

@ -146,4 +146,8 @@ return [
false,
'#,##0.00 "dollars"',
],
[
true,
'"date " y-m-d',
],
];

Binary file not shown.