diff --git a/composer.json b/composer.json new file mode 100644 index 00000000000..101810bb959 --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpoffice/phpspreadsheet": "^1.12" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000000..84bcb989348 --- /dev/null +++ b/composer.lock @@ -0,0 +1,339 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "a68ce168cd747e78b793f2d2d0bb89b9", + "packages": [ + { + "name": "markbaker/complex", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "c3131244e29c08d44fefb49e0dd35021e9e39dd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/c3131244e29c08d44fefb49e0dd35021e9e39dd2", + "reference": "c3131244e29c08d44fefb49e0dd35021e9e39dd2", + "shasum": "" + }, + "require": { + "php": "^5.6.0|^7.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0|^5.0|^6.0|^7.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.35|^5.0|^6.0|^7.0", + "sebastian/phpcpd": "2.*", + "squizlabs/php_codesniffer": "^3.4.0" + }, + "type": "library", + "autoload": { + "files": [ + "classes/src/functions/abs.php", + "classes/src/functions/acos.php", + "classes/src/functions/acosh.php", + "classes/src/functions/acot.php", + "classes/src/functions/acoth.php", + "classes/src/functions/acsc.php", + "classes/src/functions/acsch.php", + "classes/src/functions/argument.php", + "classes/src/functions/asec.php", + "classes/src/functions/asech.php", + "classes/src/functions/asin.php", + "classes/src/functions/asinh.php", + "classes/src/functions/atan.php", + "classes/src/functions/atanh.php", + "classes/src/functions/conjugate.php", + "classes/src/functions/cos.php", + "classes/src/functions/cosh.php", + "classes/src/functions/cot.php", + "classes/src/functions/coth.php", + "classes/src/functions/csc.php", + "classes/src/functions/csch.php", + "classes/src/functions/exp.php", + "classes/src/functions/inverse.php", + "classes/src/functions/ln.php", + "classes/src/functions/log2.php", + "classes/src/functions/log10.php", + "classes/src/functions/negative.php", + "classes/src/functions/pow.php", + "classes/src/functions/rho.php", + "classes/src/functions/sec.php", + "classes/src/functions/sech.php", + "classes/src/functions/sin.php", + "classes/src/functions/sinh.php", + "classes/src/functions/sqrt.php", + "classes/src/functions/tan.php", + "classes/src/functions/tanh.php", + "classes/src/functions/theta.php", + "classes/src/operations/add.php", + "classes/src/operations/subtract.php", + "classes/src/operations/multiply.php", + "classes/src/operations/divideby.php", + "classes/src/operations/divideinto.php" + ], + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/1.5.0" + }, + "time": "2020-08-26T19:47:57+00:00" + }, + { + "name": "markbaker/matrix", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "44bb1ab01811116f01fe216ab37d921dccc6c10d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/44bb1ab01811116f01fe216ab37d921dccc6c10d", + "reference": "44bb1ab01811116f01fe216ab37d921dccc6c10d", + "shasum": "" + }, + "require": { + "php": "^5.6.0|^7.0.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "dev-master", + "phploc/phploc": "^4", + "phpmd/phpmd": "dev-master", + "phpunit/phpunit": "^5.7|^6.0|7.0", + "sebastian/phpcpd": "^3.0", + "squizlabs/php_codesniffer": "^3.0@dev" + }, + "type": "library", + "autoload": { + "files": [ + "classes/src/Functions/adjoint.php", + "classes/src/Functions/antidiagonal.php", + "classes/src/Functions/cofactors.php", + "classes/src/Functions/determinant.php", + "classes/src/Functions/diagonal.php", + "classes/src/Functions/identity.php", + "classes/src/Functions/inverse.php", + "classes/src/Functions/minors.php", + "classes/src/Functions/trace.php", + "classes/src/Functions/transpose.php", + "classes/src/Operations/add.php", + "classes/src/Operations/directsum.php", + "classes/src/Operations/subtract.php", + "classes/src/Operations/multiply.php", + "classes/src/Operations/divideby.php", + "classes/src/Operations/divideinto.php" + ], + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/1.2.3" + }, + "time": "2021-01-26T14:36:01+00:00" + }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "f79611d6dc1f6b7e8e30b738fc371b392001dbfd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/f79611d6dc1f6b7e8e30b738fc371b392001dbfd", + "reference": "f79611d6dc1f6b7e8e30b738fc371b392001dbfd", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "markbaker/complex": "^1.4", + "markbaker/matrix": "^1.2", + "php": "^7.1", + "psr/simple-cache": "^1.0" + }, + "require-dev": { + "dompdf/dompdf": "^0.8.3", + "friendsofphp/php-cs-fixer": "^2.16", + "jpgraph/jpgraph": "^4.0", + "mpdf/mpdf": "^8.0", + "phpcompatibility/php-compatibility": "^9.3", + "phpunit/phpunit": "^7.5", + "squizlabs/php_codesniffer": "^3.5", + "tecnickcom/tcpdf": "^6.3" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.12.0" + }, + "time": "2020-04-27T08:12:48+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.0.0" +} diff --git a/htdocs/core/modules/export/export_excel2007.modules.php b/htdocs/core/modules/export/export_excel2007.modules.php index 92feafb3859..ea7480cf15c 100644 --- a/htdocs/core/modules/export/export_excel2007.modules.php +++ b/htdocs/core/modules/export/export_excel2007.modules.php @@ -92,7 +92,7 @@ class ExportExcel2007 extends ModeleExports if (empty($this->disabled)) { require_once PHPEXCELNEW_PATH.'Spreadsheet.php'; $this->label_lib = 'PhpSpreadSheet'; - $this->version_lib = '1.6.0'; // No way to get info from library + $this->version_lib = '1.12.0'; // No way to get info from library } $this->row = 0; diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index b6286c35162..27c15bda16f 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -41,7 +41,7 @@ class modFournisseur extends DolibarrModules */ public function __construct($db) { - global $conf, $user; + global $conf, $langs, $user; $this->db = $db; $this->numero = 40; @@ -309,6 +309,8 @@ class modFournisseur extends DolibarrModules //-------- $r = 0; + $langs->loadLangs(array("suppliers", "multicurrency")); + $r++; $this->export_code[$r] = $this->rights_class.'_'.$r; $this->export_label[$r] = 'Vendor invoices and lines of invoices'; diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index e9602cc3e79..e62f2b0e07e 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -765,7 +765,7 @@ class modProduct extends DolibarrModules 'sp.quantity' => "QtyMin*", 'sp.tva_tx' => 'VATRate', 'sp.default_vat_code' => 'VATCode', - 'sp.delivery_time_days' => 'DeliveryDelay', + 'sp.delivery_time_days' => 'NbDaysToDelivery', 'sp.supplier_reputation' => 'SupplierReputation', 'sp.status' => 'Status' ); diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index a316c746acb..b4a6d2f6025 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -722,7 +722,7 @@ class modService extends DolibarrModules 'sp.quantity' => "QtyMin*", 'sp.tva_tx' => 'VATRate', 'sp.default_vat_code' => 'VATCode', - 'sp.delivery_time_days' => 'DeliveryDelay', + 'sp.delivery_time_days' => 'NbDaysToDelivery', 'sp.supplier_reputation' => 'SupplierReputation' ); if (is_object($mysoc) && $usenpr) { diff --git a/htdocs/core/modules/modSupplierProposal.class.php b/htdocs/core/modules/modSupplierProposal.class.php index c775744c6e7..674ba46601a 100644 --- a/htdocs/core/modules/modSupplierProposal.class.php +++ b/htdocs/core/modules/modSupplierProposal.class.php @@ -36,7 +36,6 @@ include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; */ class modSupplierProposal extends DolibarrModules { - /** * Constructor. Define names, constants, directories, boxes, permissions * diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index f35ae3a3121..1afd41c6027 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -1180,7 +1180,8 @@ if ($step == 5 && $datatoexport) { print '
'; // List of available export formats - $htmltabloflibs = ''; + $htmltabloflibs = '
'; + $htmltabloflibs .= '
'; $htmltabloflibs .= ''; $htmltabloflibs .= ''; $htmltabloflibs .= ''; @@ -1204,7 +1205,7 @@ if ($step == 5 && $datatoexport) { $htmltabloflibs .= ''; $htmltabloflibs .= ''."\n"; } - $htmltabloflibs .= '
'.$langs->trans("AvailableFormats").''.$langs->trans("LibraryUsed").''.$objmodelexport->getLibVersionForKey($key).'
'; + $htmltabloflibs .= '
'; print ''.$form->textwithpicto($langs->trans("NowClickToGenerateToBuildExportFile"), $htmltabloflibs, 1, 'help', '', 0, 2, 'helphonformat').''; //print $htmltabloflibs; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/.gitattributes b/htdocs/includes/phpoffice/phpspreadsheet/.gitattributes new file mode 100644 index 00000000000..0375f558339 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/.gitattributes @@ -0,0 +1,4 @@ +/tests export-ignore +README.md export-ignore +*.min.js binary +/.github export-ignore diff --git a/htdocs/includes/phpoffice/phpspreadsheet/.gitignore b/htdocs/includes/phpoffice/phpspreadsheet/.gitignore new file mode 100644 index 00000000000..0723541d7af --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/.gitignore @@ -0,0 +1,10 @@ +/tests/codeCoverage +/analysis +/vendor/ +/phpunit.xml + +## IDE support +*.buildpath +*.project +/.settings +/.idea diff --git a/htdocs/includes/phpoffice/phpspreadsheet/.php_cs.dist b/htdocs/includes/phpoffice/phpspreadsheet/.php_cs.dist new file mode 100644 index 00000000000..23216924880 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/.php_cs.dist @@ -0,0 +1,183 @@ +exclude(['vendor', 'tests/data/Calculation']) + ->in('samples') + ->in('src') + ->in('tests/PhpSpreadsheetTests') + ; + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setFinder($finder) + ->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer' . preg_replace('~\W~', '-', __DIR__)) + ->setRules([ + 'align_multiline_comment' => true, + 'array_syntax' => ['syntax' => 'short'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'braces' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => ['elements' => ['method', 'property']], // const are often grouped with other related const + 'class_definition' => true, + 'class_keyword_remove' => false, // ::class keyword gives us beter support in IDE + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => true, + 'declare_strict_types' => false, // Too early to adopt strict types + 'dir_constant' => true, + 'doctrine_annotation_array_assignment' => true, + 'doctrine_annotation_braces' => true, + 'doctrine_annotation_indentation' => true, + 'doctrine_annotation_spaces' => true, + 'elseif' => true, + 'encoding' => true, + 'ereg_to_preg' => true, + 'escape_implicit_backslashes' => true, + 'explicit_indirect_variable' => false, // I feel it makes the code actually harder to read + 'explicit_string_variable' => false, // I feel it makes the code actually harder to read + 'final_internal_class' => true, + 'full_opening_tag' => true, + 'function_declaration' => true, + 'function_to_constant' => true, + 'function_typehint_space' => true, + 'general_phpdoc_annotation_remove' => false, // No use for that + 'hash_to_slash_comment' => true, + 'header_comment' => false, // We don't use common header in all our files + 'heredoc_to_nowdoc' => false, // Not sure about this one + 'include' => true, + 'increment_style' => true, + 'indentation_type' => true, + 'is_null' => ['use_yoda_style' => false], + 'linebreak_after_opening_tag' => true, + 'line_ending' => true, + 'list_syntax' => ['syntax' => 'short'], + 'lowercase_cast' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'magic_constant_casing' => true, + 'mb_str_functions' => false, // No, too dangerous to change that + 'method_argument_space' => true, + 'method_chaining_indentation' => true, + 'method_separation' => true, + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'native_function_casing' => true, + 'native_function_invocation' => false, // This is risky and seems to be micro-optimization that make code uglier so not worth it, at least for now + 'new_with_braces' => true, + 'no_alias_functions' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => false, // we want 1 blank line before namespace + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_multiline_whitespace_before_semicolons' => true, + 'non_printable_character' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'normalize_index_brace' => true, + 'no_short_bool_cast' => true, + 'no_short_echo_tag' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => false, // Might be risky on a huge code base + 'not_operator_with_space' => false, // No we prefer to keep '!' without spaces + 'not_operator_with_successor_space' => false, // idem + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_trailing_whitespace' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => false, // We prefer to keep some freedom + 'ordered_imports' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => false, // Waste of time + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_inline_tag' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_types_order' => true, + 'phpdoc_types' => true, + 'phpdoc_var_without_name' => true, + 'php_unit_construct' => true, + 'php_unit_dedicate_assert' => true, + 'php_unit_expectation' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_mock' => true, + 'php_unit_namespaced' => true, + 'php_unit_no_expectation_annotation' => true, + 'php_unit_strict' => false, // We sometime actually need assertEquals + 'php_unit_test_annotation' => true, + 'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage + 'pow_to_exponentiation' => false, + 'protected_to_private' => true, + 'psr0' => true, + 'psr4' => true, + 'random_api_migration' => false, // This breaks our unit tests + 'return_type_declaration' => true, + 'self_accessor' => true, + 'semicolon_after_instruction' => false, // Buggy in `samples/index.php` + 'short_scalar_cast' => true, + 'silenced_deprecation_error' => true, + 'simplified_null_return' => false, // While technically correct we prefer to be explicit when returning null + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_style' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'standardize_not_equals' => true, + 'static_lambda' => false, // Risky if we can't guarantee nobody use `bindTo()` + 'strict_comparison' => false, // No, too dangerous to change that + 'strict_param' => false, // No, too dangerous to change that + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline_array' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => true, + 'void_return' => false, // Cannot use that with PHP 5.6 + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => false, + ]); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/.scrutinizer.yml b/htdocs/includes/phpoffice/phpspreadsheet/.scrutinizer.yml new file mode 100644 index 00000000000..748f3ac3fa1 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/.scrutinizer.yml @@ -0,0 +1,27 @@ +checks: + php: true + +coding_style: + php: + spaces: + before_parentheses: + closure_definition: true + around_operators: + concatenation: true + +build: + nodes: + analysis: + tests: + override: + - php-scrutinizer-run + +tools: + external_code_coverage: + timeout: 3600 + +build_failure_conditions: + - 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed + - 'issues.severity(>= MAJOR).new.exists' # New issues of major or higher severity + - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection + - 'patches.label("Unused Use Statements").new.exists' # No new unused imports patches allowed diff --git a/htdocs/includes/phpoffice/phpspreadsheet/.travis.yml b/htdocs/includes/phpoffice/phpspreadsheet/.travis.yml new file mode 100644 index 00000000000..82e25cee1aa --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/.travis.yml @@ -0,0 +1,57 @@ +language: php +dist: bionic + +php: + - 7.1 + - 7.2 + - 7.3 + - 7.4 + +cache: + directories: + - vendor + - $HOME/.composer/cache + +before_script: + # Deactivate xdebug + - phpenv config-rm xdebug.ini + - composer install --ignore-platform-reqs + +script: + - ./vendor/bin/phpunit + +jobs: + include: + + - stage: Code style + php: 7.2 + script: + - ./vendor/bin/php-cs-fixer fix --diff --verbose --dry-run + - ./vendor/bin/phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n + + - stage: Coverage + php: 7.2 + script: + - pecl install pcov + - composer require pcov/clobber --dev + - ./vendor/bin/pcov clobber + - ./vendor/bin/phpunit --coverage-clover coverage-clover.xml + after_script: + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover tests/coverage-clover.xml + + - stage: API documentations + if: tag is present + php: 7.4 + before_script: + - curl -O https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/phpDocumentor.phar + script: + - php phpDocumentor.phar --directory src/ --target docs/api + deploy: + provider: pages + skip-cleanup: true + local-dir: docs/api + github-token: $GITHUB_TOKEN + on: + all_branches: true + condition: $TRAVIS_BRANCH =~ ^master$ diff --git a/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.PHPExcel.md b/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.PHPExcel.md new file mode 100644 index 00000000000..3c299020ed0 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.PHPExcel.md @@ -0,0 +1,1593 @@ +# Changelog for PHPExcel + +This is the historic changelog of the project when it was still called PHPExcel. +It exists only for historical purposes and versions mentioned here should not be +confused with PhpSpreadsheet versions. + +## [1.8.1] - 2015-04-30 + +### Bugfixes + +- Fix for Writing an Open Document cell with non-numeric formula - @goncons [#397](https://github.com/PHPOffice/PHPExcel/issues/397) +- Avoid potential divide by zero in basedrawing - @sarciszewski [#329](https://github.com/PHPOffice/PHPExcel/issues/329) +- XML External Entity (XXE) Processing, different behaviour between simplexml_load_string() and simplexml_load_file(). - @ymaerschalck [#405](https://github.com/PHPOffice/PHPExcel/issues/405) +- Fix to ensure that current cell is maintained when executing formula calculations - @MarkBaker +- Keep/set the value on Reader _loadSheetsOnly as NULL, courtesy of Restless-ET - @MarkBaker [#350](https://github.com/PHPOffice/PHPExcel/issues/350) +- Loading an Excel 2007 spreadsheet throws an "Autofilter must be set on a range of cells" exception - @MarkBaker [CodePlex #18105](https://phpexcel.codeplex.com/workitem/18105) +- Fix to autoloader registration for backward compatibility with PHP 5.2.0 not accepting the prepend flag - @MarkBaker [#388](https://github.com/PHPOffice/PHPExcel/issues/388) +- DOM loadHTMLFile() failing with options flags when using PHP < 5.4.0 - @MarkBaker [#384](https://github.com/PHPOffice/PHPExcel/issues/384) +- Fix for percentage operator in formulae for BIFF Writer - @MarkBaker +- Fix to getStyle() call for cell object - @MarkBaker +- Discard Autofilters in Excel2007 Reader when filter range isn't a valid range - @MarkBaker +- Fix invalid NA return in VLOOKUP - @frozenstupidity [#423](https://github.com/PHPOffice/PHPExcel/issues/423) +- "No Impact" conditional formatting fix for NumberFormat - @wiseloren [CodePlex #21454](https://phpexcel.codeplex.com/workitem/21454) +- Bug in Excel2003XML reader, parsing merged cells - @bobwitlox [#467](https://github.com/PHPOffice/PHPExcel/issues/467) +- Fix for CEIL() and FLOOR() when number argument is zero - @MarkBaker [#302](https://github.com/PHPOffice/PHPExcel/issues/302) + +### General + +- Remove cells cleanly when calling RemoveRow() or RemoveColumn() - @MarkBaker +- Small performance improvement for autosize columns - @MarkBaker +- Change the getter/setter for zeroHeight to camel case - @frost-nzcr4 [#379](https://github.com/PHPOffice/PHPExcel/issues/379) +- DefaultValueBinder is too much aggressive when converting string to numeric - @MarkBaker [#394](https://github.com/PHPOffice/PHPExcel/issues/394) +- Default precalculate formulas to false for writers - @MarkBaker +- Set default Cyclic Reference behaviour to 1 to eliminate exception when using a single cyclic iteration in formulae - @MarkBaker + +### Features + +- Some Excel writer libraries erroneously use Codepage 21010 for UTF-16LE - @MarkBaker [#396](https://github.com/PHPOffice/PHPExcel/issues/396) +- Methods to manage most of the existing options for Chart Axis, Major Grid-lines and Minor Grid-lines - @WiktrzGE [#404](https://github.com/PHPOffice/PHPExcel/issues/404) +- ODS read/write comments in the cell - @frost-nzcr4 [#403](https://github.com/PHPOffice/PHPExcel/issues/403) +- Additional Mac CJK codepage definitions - @CQD [#389](https://github.com/PHPOffice/PHPExcel/issues/389) +- Update Worksheet.php getStyleByColumnAndRow() to allow a range of cells rather than just a single cell - @bolovincev [#269](https://github.com/PHPOffice/PHPExcel/issues/269) +- New methods added for testing cell status within merge groups - @MarkBaker +- Handling merge cells in HTML Reader - @cifren/MBaker [#205](https://github.com/PHPOffice/PHPExcel/issues/205) +- Helper to convert basic HTML markup to a Rich Text object - @MarkBaker +- Improved Iterators - @MarkBaker + - New Column Iterator + - Support for row and column ranges + - Improved handling for next/prev + +### Security + +- XML filescan in XML-based Readers to prevent XML Entity Expansion (XEE) - @MarkBaker + - (see http://projects.webappsec.org/w/page/13247002/XML%20Entity%20Expansion for an explanation of XEE injection) attacks + - Reference CVE-2015-3542 - Identification of problem courtesy of Dawid Golunski (Pentest Ltd.) + +## [1.8.0] - 2014-03-02 + +### Bugfixes + +- Undefined variable: fileHandle in CSV Reader - @MarkBaker [CodePlex #19830](https://phpexcel.codeplex.com/workitem/19830) +- Out of memory in style/supervisor.php - @MarkBaker [CodePlex #19968](https://phpexcel.codeplex.com/workitem/19968) +- Style error with merged cells in PDF Writer - @MarkBaker +- Problem with cloning worksheets - @MarkBaker +- Bug fix reading Open Office files - @tavoarcila [#259](https://github.com/PHPOffice/PHPExcel/issues/259) +- Serious bug in absolute cell reference used in shared formula - @MarkBaker [CodePlex #20397](https://phpexcel.codeplex.com/workitem/20397) + - Would also have affected insert/delete column/row- CHOOSE() returns "#VALUE!" if the 1st entry is chosen - @RomanSyroeshko [#267](https://github.com/PHPOffice/PHPExcel/issues/267) +- When duplicating styles, styles shifted by one column to the right - @Gemorroj [#268](https://github.com/PHPOffice/PHPExcel/issues/268) + - Fix also applied to duplicating conditional styles- Fix for formulae that reference a sheet whose name begins with a digit: - @IndrekHaav [#212](https://github.com/PHPOffice/PHPExcel/issues/212) + - these were erroneously identified as numeric values, causing the parser to throw an undefined variable error.- Fixed undefined variable error due to $styleArray being used before it's initialised - @IndrekHaav [CodePlex #16208](https://phpexcel.codeplex.com/workitem/16208) +- ISTEXT() return wrong result if referencing an empty but formatted cell - @PowerKiKi [#273](https://github.com/PHPOffice/PHPExcel/issues/273) +- Binary comparison of strings are case insensitive - @PowerKiKi [#270](https://github.com/PHPOffice/PHPExcel/issues/270), [#31](https://github.com/PHPOffice/PHPExcel/issues/31) +- Insert New Row/Column Before is not correctly updating formula references - @MarkBaker [#275](https://github.com/PHPOffice/PHPExcel/issues/275) +- Passing an array of cells to _generateRow() in the HTML/PDF Writer causes caching problems with last cell in the range - @MarkBaker [#257](https://github.com/PHPOffice/PHPExcel/issues/257) +- Fix to empty worksheet garbage collection when using cell caching - @MarkBaker [#193](https://github.com/PHPOffice/PHPExcel/issues/193) +- Excel2007 does not correctly mark rows as hidden - @Jazzo [#248](https://github.com/PHPOffice/PHPExcel/issues/248) +- Fixed typo in Chart/Layout set/getYMode() - @Roy Shahbazian [#299](https://github.com/PHPOffice/PHPExcel/issues/299) +- Fatal error: Call to a member function cellExists() line: 3327 in calculation.php if referenced worksheet doesn't exist - @EliuFlorez [#279](https://github.com/PHPOffice/PHPExcel/issues/279) +- AdvancedValueBinder "Division by zero"-error - @MarkBaker [#290](https://github.com/PHPOffice/PHPExcel/issues/290) +- Adding Sheet to Workbook Bug - @MarkBaker [CodePlex #20604](https://phpexcel.codeplex.com/workitem/20604) +- Calculation engine incorrectly evaluates empty cells as #VALUE - @MarkBaker [CodePlex #20703](https://phpexcel.codeplex.com/workitem/20703) +- Formula references to cell on another sheet in ODS files - @MarkBaker [CodePlex #20760](https://phpexcel.codeplex.com/workitem/20760) + +### Features + +- LibreOffice created XLSX files results in an empty file. - @MarkBaker [#321](https://github.com/PHPOffice/PHPExcel/issues/321), [#158](https://github.com/PHPOffice/PHPExcel/issues/158), [CodePlex #17824](https://phpexcel.codeplex.com/workitem/17824) +- Implementation of the Excel HLOOKUP() function - @amerov +- Added "Quote Prefix" to style settings (Excel2007 Reader and Writer only) - @MarkBaker +- Added Horizontal FILL alignment for Excel5 and Excel2007 Readers/Writers, and Horizontal DISTRIBUTED alignment for Excel2007 Reader/Writer - @MarkBaker +- Add support for reading protected (RC4 encrypted) .xls files - @trvrnrth [#261](https://github.com/PHPOffice/PHPExcel/issues/261) + +### General + +- Adding support for macros, Ribbon in Excel 2007 - @LWol [#252](https://github.com/PHPOffice/PHPExcel/issues/252) +- Remove array_shift in ReferenceHelper::insertNewBefore improves column or row delete speed - @cdhutch [CodePlex #20055](https://phpexcel.codeplex.com/workitem/20055) +- Improve stock chart handling and rendering, with help from Swashata Ghosh - @MarkBaker +- Fix to calculation properties for Excel2007 so that the opening application will only recalculate on load if it's actually required - @MarkBaker +- Modified Excel2007 Writer to default preCalculateFormulas to false - @MarkBaker + - Note that autosize columns will still recalculate affected formulae internally- Functionality to getHighestRow() for a specified column, and getHighestColumn() for a specified row - @dresenhista [#242](https://github.com/PHPOffice/PHPExcel/issues/242) +- Modify PHPExcel_Reader_Excel2007 to use zipClass from PHPExcel_Settings::getZipClass() - @adamriyadi [#247](https://github.com/PHPOffice/PHPExcel/issues/247) + - This allows the use of PCLZip when reading for people that don't have access to ZipArchive +### Security + +- Convert properties to string in OOCalc reader - @infojunkie [#276](https://github.com/PHPOffice/PHPExcel/issues/276) +- Disable libxml external entity loading by default. - @maartenba [#322](https://github.com/PHPOffice/PHPExcel/issues/322) + - This is to prevent XML External Entity Processing (XXE) injection attacks (see https://websec.io/2012/08/27/Preventing-XEE-in-PHP.html for an explanation of XXE injection). + - Reference CVE-2014-2054 + +## [1.7.9] - 2013-06-02 + +### Features + +- Include charts option for HTML Writer - @MarkBaker +- Added composer file - @MarkBaker +- cache_in_memory_gzip "eats" last worksheet line, cache_in_memory doesn't - @MarkBaker [CodePlex #18844](https://phpexcel.codeplex.com/workitem/18844) +- echo statements in HTML.php - @MarkBaker [#104](https://github.com/PHPOffice/PHPExcel/issues/104) + +### Bugfixes + +- Added getStyle() method to Cell object - @MarkBaker +- Error in PHPEXCEL/Calculation.php script on line 2976 (stack pop check) - @Asker [CodePlex #18777](https://phpexcel.codeplex.com/workitem/18777) +- CSV files without a file extension being identified as HTML - @MarkBaker [CodePlex #18794](https://phpexcel.codeplex.com/workitem/18794) +- Wrong check for maximum number of rows in Excel5 Writer - @AndreKR [#66](https://github.com/PHPOffice/PHPExcel/issues/66) +- Cache directory for DiscISAM cache storage cannot be set - @MarkBaker [#67](https://github.com/PHPOffice/PHPExcel/issues/67) +- Fix to Excel2007 Reader for hyperlinks with an anchor fragment (following a #), otherwise they were treated as sheet references - @MarkBaker [CodePlex #17976](https://phpexcel.codeplex.com/workitem/17976) +- getSheetNames() fails on numeric (floating point style) names with trailing zeroes - @MarkBaker [CodePlex #18963](https://phpexcel.codeplex.com/workitem/18963) +- Modify cell's getCalculatedValue() method to return the content of RichText objects rather than the RichText object itself - @MarkBaker +- Fixed formula/formatting bug when removing rows - @techhead [#70](https://github.com/PHPOffice/PHPExcel/issues/70) +- Fix to cellExists for non-existent namedRanges - @alexgann [#63](https://github.com/PHPOffice/PHPExcel/issues/63) +- Sheet View in Excel5 Writer - @Progi1984 [#22](https://github.com/PHPOffice/PHPExcel/issues/22) +- PHPExcel_Worksheet::getCellCollection() may not return last cached cell - @amironov [#82](https://github.com/PHPOffice/PHPExcel/issues/82) +- Rich Text containing UTF-8 characters creating unreadable content with Excel5 Writer - @teso [CodePlex #18551](https://phpexcel.codeplex.com/workitem/18551) +- Work item GH-8/CP11704 : Conditional formatting in Excel 5 Writer - @Progi1984 +- canRead() Error for GoogleDocs ODS files: in ODS files from Google Docs there is no mimetype file - @MarkBaker [#113](https://github.com/PHPOffice/PHPExcel/issues/113) +- "Sheet index is out of bounds." Exception - @MarkBaker [#80](https://github.com/PHPOffice/PHPExcel/issues/80) +- Fixed number format fatal error - @ccorliss [#105](https://github.com/PHPOffice/PHPExcel/issues/105) +- Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers - @MarkBaker +- Fix merged-cell borders on HTML/PDF output - @alexgann [#154](https://github.com/PHPOffice/PHPExcel/issues/154) +- Fix: Hyperlinks break when removing rows - @Shanto [#161](https://github.com/PHPOffice/PHPExcel/issues/161) +- Fix Extra Table Row From Images and Charts - @neclimdul [#166](https://github.com/PHPOffice/PHPExcel/issues/166) + +### General + +- Single cell print area - @MarkBaker [#130](https://github.com/PHPOffice/PHPExcel/issues/130) +- Improved AdvancedValueBinder for currency - @kea [#69](https://github.com/PHPOffice/PHPExcel/issues/69) +- Fix for environments where there is no access to /tmp but to upload_tmp_dir - @MarkBaker + - Provided an option to set the sys_get_temp_dir() call to use the upload_tmp_dir; though by default the standard temp directory will still be used- Search style by identity in PHPExcel_Worksheet::duplicateStyle() - @amironov [#84](https://github.com/PHPOffice/PHPExcel/issues/84) +- Fill SheetView IO in Excel5 - @karak [#85](https://github.com/PHPOffice/PHPExcel/issues/85) +- Memory and Speed improvements in PHPExcel_Reader_Excel5 - @cfhay [CodePlex #18958](https://phpexcel.codeplex.com/workitem/18958) +- Modify listWorksheetNames() and listWorksheetInfo to use XMLReader with streamed XML rather than SimpleXML - @MarkBaker [#78](https://github.com/PHPOffice/PHPExcel/issues/78) +- Restructuring of PHPExcel Exceptions - @dbonsch +- Refactor Calculation Engine from singleton to a Multiton - @MarkBaker + - Ensures that calculation cache is maintained independently for different workbooks + +## [1.7.8] - 2012-10-12 + +### Features + +- Phar builder script to add phar file as a distribution option - @kkamkou +- Refactor PDF Writer to allow use with a choice of PDF Rendering library - @MarkBaker + - rather than restricting to tcPDF + - Current options are tcPDF, mPDF, DomPDF + - tcPDF Library has now been removed from the deployment bundle- Initial version of HTML Reader - @MarkBaker +- Implement support for AutoFilter in PHPExcel_Writer_Excel5 - @Progi1984 +- Modified ERF and ERFC Engineering functions to accept Excel 2010's modified acceptance of negative arguments - @MarkBaker +- Support SheetView `view` attribute (Excel2007) - @k1LoW +- Excel compatibility option added for writing CSV files - @MarkBaker + - While Excel 2010 can read CSV files with a simple UTF-8 BOM, Excel2007 and earlier require UTF-16LE encoded tab-separated files. + - The new setExcelCompatibility(TRUE) option for the CSV Writer will generate files with this formatting for easy import into Excel2007 and below.- Language implementations for Turkish (tr) - @MarkBaker +- Added fraction tests to advanced value binder - @MarkBaker + +### General + +- Allow call to font setUnderline() for underline format to specify a simple boolean for UNDERLINE_NONE or UNDERLINE_SINGLE - @MarkBaker +- Add Currency detection to the Advanced Value Binder - @alexgann +- setCellValueExplicitByColumnAndRow() do not return PHPExcel_Worksheet - @MarkBaker [CodePlex #18404](https://phpexcel.codeplex.com/workitem/18404) +- Reader factory doesn't read anymore XLTX and XLT files - @MarkBaker [CodePlex #18324](https://phpexcel.codeplex.com/workitem/18324) +- Magic __toString() method added to Cell object to return raw data value as a string - @MarkBaker +- Add cell indent to html rendering - @alexgann + +### Bugfixes + +- ZeroHeight for rows in sheet format - @Raghav1981 +- OOCalc cells containing inside the tag - @cyberconte +- Fix to listWorksheetInfo() method for OOCalc Reader - @schir1964 +- Support for "e" (epoch) date format mask - @MarkBaker + - Rendered as a 4-digit CE year in non-Excel outputs- Background color cell is always black when editing cell - @MarkBaker +- Allow "no impact" to formats on Conditional Formatting - @MarkBaker +- OOCalc Reader fix for NULL cells - @wackonline +- Fix to excel2007 Chart Writer when a $plotSeriesValues is empty - @seltzlab +- Various fixes to Chart handling - @MarkBaker +- Error loading xlsx file with column breaks - @MarkBaker [CodePlex #18370](https://phpexcel.codeplex.com/workitem/18370) +- OOCalc Reader now handles percentage and currency data types - @MarkBaker +- mb_stripos empty delimiter - @MarkBaker +- getNestingLevel() Error on Excel5 Read - @takaakik +- Fix to Excel5 Reader when cell annotations are defined before their referenced text objects - @MarkBaker +- OOCalc Reader modified to process number-rows-repeated - @MarkBaker +- Chart Title compatibility on Excel 2007 - @MarkBaker [CodePlex #18377](https://phpexcel.codeplex.com/workitem/18377) +- Chart Refresh returning cell reference rather than values - @MarkBaker [CodePlex #18146](https://phpexcel.codeplex.com/workitem/18146) +- Autoshape being identified in twoCellAnchor when includeCharts is TRUE triggering load error - @MarkBaker [CodePlex #18145](https://phpexcel.codeplex.com/workitem/18145) +- v-type texts for series labels now recognised and parsed correctly - @MarkBaker [CodePlex #18325](https://phpexcel.codeplex.com/workitem/18325) +- load file failed if the file has no extensionType - @wolf5x [CodePlex #18492](https://phpexcel.codeplex.com/workitem/18492) +- Pattern fill colours in Excel2007 Style Writer - @dverspui +- Excel2007 Writer order of font style elements to conform with Excel2003 using compatibility pack - @MarkBaker +- Problems with $_activeSheetIndex when decreased below 0. - @MarkBaker [CodePlex #18425](https://phpexcel.codeplex.com/workitem/18425) +- PHPExcel_CachedObjectStorage_SQLite3::cacheMethodIsAvailable() uses class_exists - autoloader throws error - @MarkBaker [CodePlex #18597](https://phpexcel.codeplex.com/workitem/18597) +- Cannot access private property PHPExcel_CachedObjectStorageFactory::$_cacheStorageMethod - @MarkBaker [CodePlex #18598](https://phpexcel.codeplex.com/workitem/18598) +- Data titles for charts - @MarkBaker [CodePlex #18397](https://phpexcel.codeplex.com/workitem/18397) + - PHPExcel_Chart_Layout now has methods for getting/setting switches for displaying/hiding chart data labels- Discard single cell merge ranges when reading (stupid that Excel allows them in the first place) - @MarkBaker +- Discard hidden autoFilter named ranges - @MarkBaker + +## [1.7.7] - 2012-05-19 + +### Bugfixes + +- Support for Rich-Text in PHPExcel_Writer_Excel5 - @Progi1984 [CodePlex #8916](https://phpexcel.codeplex.com/workitem/8916) +- Change iterators to implement Iterator rather than extend CachingIterator, as a fix for PHP 5.4. changes in SPL - @MarkBaker +- Invalid cell coordinate in Autofilter for Excel2007 Writer - @MarkBaker [CodePlex #15459](https://phpexcel.codeplex.com/workitem/15459) +- PCLZip library issue - @MarkBaker [CodePlex #15518](https://phpexcel.codeplex.com/workitem/15518) +- Excel2007 Reader canRead function bug - @MarkBaker [CodePlex #15537](https://phpexcel.codeplex.com/workitem/15537) +- Support for Excel functions whose return can be used as either a value or as a cell reference depending on its context within a formula - @MarkBaker +- ini_set() call in Calculation class destructor - @gilles06 [CodePlex #15707](https://phpexcel.codeplex.com/workitem/15707) +- RangeToArray strange array keys - @MarkBaker [CodePlex #15786](https://phpexcel.codeplex.com/workitem/15786) +- INDIRECT() function doesn't work with named ranges - @MarkBaker [CodePlex #15762](https://phpexcel.codeplex.com/workitem/15762) +- Locale-specific fix to text functions when passing a boolean argument instead of a string - @MarkBaker +- reader/CSV fails on this file - @MarkBaker [CodePlex #16246](https://phpexcel.codeplex.com/workitem/16246) + - auto_detect_line_endings now set in CSV reader- $arguments improperly used in CachedObjectStorage/PHPTemp.php - @MarkBaker [CodePlex #16212](https://phpexcel.codeplex.com/workitem/16212) +- Bug In Cache System (cell reference when throwing caching errors) - @MarkBaker [CodePlex #16643](https://phpexcel.codeplex.com/workitem/16643) +- PHP Invalid index notice on writing excel file when active sheet has been deleted - @MarkBaker [CodePlex #16895](https://phpexcel.codeplex.com/workitem/16895) +- External links in Excel2010 files cause Fatal error - @MarkBaker [CodePlex #16956](https://phpexcel.codeplex.com/workitem/16956) +- Previous calculation engine error conditions trigger cyclic reference errors - @MarkBaker [CodePlex #16960](https://phpexcel.codeplex.com/workitem/16960) +- PHPExcel_Style::applyFromArray() returns null rather than style object in advanced mode - @mkopinsky [CodePlex #16266](https://phpexcel.codeplex.com/workitem/16266) +- Cell::getFormattedValue returns RichText object instead of string - @fauvel [CodePlex #16958](https://phpexcel.codeplex.com/workitem/16958) +- Indexed colors do not refer to Excel's indexed colors? - @MarkBaker [CodePlex #17166](https://phpexcel.codeplex.com/workitem/17166) +- Indexed colors should be consistent with Excel and start from 1 (current index starts at 0) - @MarkBaker [CodePlex #17199](https://phpexcel.codeplex.com/workitem/17199) +- Named Range definition in .xls when sheet reeference is quote wrapped - @MarkBaker [CodePlex #17262](https://phpexcel.codeplex.com/workitem/17262) +- duplicateStyle() method doesn't duplicate conditional formats - @MarkBaker [CodePlex #17403](https://phpexcel.codeplex.com/workitem/17403) + - Added an equivalent duplicateConditionalStyle() method for duplicating conditional styles- =sumproduct(A,B) <> =sumproduct(B,A) in xlsx - @bnr [CodePlex #17501](https://phpexcel.codeplex.com/workitem/17501) + +### Features + +- OOCalc cells contain same data bug? - @cyberconte [CodePlex #17471](https://phpexcel.codeplex.com/workitem/17471) +- listWorksheetInfo() method added to Readers... courtesy of Christopher Mullins - @schir1964 +- Options for cell caching using Igbinary and SQLite/SQlite3. - @MarkBaker +- Additional row iterator options: allow a start row to be defined in the constructor; seek(), and prev() methods added. - @MarkBaker +- Implement document properties in Excel5 writer - @Progi1984 [CodePlex #9759](https://phpexcel.codeplex.com/workitem/9759) + +### General + +- Implement chart functionality (EXPERIMENTAL) - @MarkBaker [CodePlex #16](https://phpexcel.codeplex.com/workitem/16) + - Initial definition of chart objects. + - Reading Chart definitions through the Excel2007 Reader + - Facility to render charts to images using the 3rd-party jpgraph library + - Writing Charts using the Excel2007 Writer- Fix to build to ensure that Examples are included with the documentation - @MarkBaker +- Reduce cell caching overhead using dirty flag to ensure that cells are only rewritten to the cache if they have actually been changed - @MarkBaker +- Improved memory usage in CSV Writer - @MarkBaker +- Improved speed and memory usage in Excel5 Writer - @MarkBaker +- Experimental - @MarkBaker + - Added getHighestDataColumn(), getHighestDataRow(), getHighestRowAndColumn() and calculateWorksheetDataDimension() methods for the worksheet that return the highest row and column that have cell records- Support for Rich-Text in PHPExcel_Writer_Excel5 - @Progi1984 [CodePlex #8916](https://phpexcel.codeplex.com/workitem/8916) +- Two easy to fix Issues concerning PHPExcel_Token_Stack (l10n/UC) - @MarkBaker [CodePlex #15405](https://phpexcel.codeplex.com/workitem/15405) +- Locale file paths not fit for windows - @MarkBaker [CodePlex #15461](https://phpexcel.codeplex.com/workitem/15461) +- Add file directory as a cache option for cache_to_discISAM - @MarkBaker [CodePlex #16643](https://phpexcel.codeplex.com/workitem/16643) +- Datatype.php & constant TYPE_NULL - @MarkBaker [CodePlex #16923](https://phpexcel.codeplex.com/workitem/16923) +- Ensure use of system temp directory for all temporary work files, unless explicitly specified - @MarkBaker +- [Patch] faster stringFromColumnIndex() - @char101 [CodePlex #16359](https://phpexcel.codeplex.com/workitem/16359) +- Fix for projects that still use old autoloaders - @whit1206 [CodePlex #16028](https://phpexcel.codeplex.com/workitem/16028) +- Unknown codepage: 10007 - @atz [CodePlex #17024](https://phpexcel.codeplex.com/workitem/17024) + - Additional Mac codepages + +## [1.7.6] - 2011-02-27 + +### Features + +- Provide option to use PCLZip as an alternative to ZipArchive. - @MarkBaker + - This allows the writing of Excel2007 files, even without ZipArchive enabled (it does require zlib), or when php_zip is one of the buggy PHP 5.2.6 or 5.2.8 versions + - It can be enabled using PHPExcel_Settings::setZipClass(PHPExcel_Settings::PCLZIP); + - Note that it is not yet implemented as an alternative to ZipArchive for those Readers that are extracting from zips- Added listWorksheetNames() method to Readers that support multiple worksheets in a workbook, allowing a user to extract a list of all the worksheet names from a file without parsing/loading the whole file. - @MarkBaker [CodePlex #14979](https://phpexcel.codeplex.com/workitem/14979) +- Speed boost and memory reduction in the Worksheet toArray() method. - @MarkBaker +- Added new rangeToArray() and namedRangeToArray() methods to the PHPExcel_Worksheet object. - @MarkBaker + - Functionally, these are identical to the toArray() method, except that they take an additional first parameter of a Range (e.g. 'B2:C3') or a Named Range name. + - Modified the toArray() method so that it actually uses rangeToArray().- Added support for cell comments in the OOCalc, Gnumeric and Excel2003XML Readers, and in the Excel5 Reader - @MarkBaker +- Improved toFormattedString() handling for Currency and Accounting formats to render currency symbols - @MarkBaker + +### Bugfixes + +- Implement more Excel calculation functions - @MarkBaker + - Implemented the DAVERAGE(), DCOUNT(), DCOUNTA(), DGET(), DMAX(), DMIN(), DPRODUCT(), DSTDEV(), DSTDEVP(), DSUM(), DVAR() and DVARP() Database functions- Simple =IF() formula disappears - @MarkBaker [CodePlex #14888](https://phpexcel.codeplex.com/workitem/14888) +- PHP Warning: preg_match(): Compilation failed: PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X - @MarkBaker [CodePlex #14898](https://phpexcel.codeplex.com/workitem/14898) +- VLOOKUP choking on parameters in PHPExcel.1.7.5/PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #14901](https://phpexcel.codeplex.com/workitem/14901) +- PHPExcel_Cell::isInRange() incorrect results - offset by one column - @MarkBaker [CodePlex #14973](https://phpexcel.codeplex.com/workitem/14973) +- Treat CodePage of 0 as CP1251 (for .xls files written by applications that don't set the CodePage correctly, such as Apple Numbers) - @MarkBaker +- Need method for removing autoFilter - @MarkBaker [CodePlex #11583](https://phpexcel.codeplex.com/workitem/11583) +- coordinateFromString throws exception for rows greater than 99,999 - @MarkBaker [CodePlex #15029](https://phpexcel.codeplex.com/workitem/15029) +- PHPExcel Excel2007 Reader colour problems with solidfill - @MarkBaker [CodePlex #14999](https://phpexcel.codeplex.com/workitem/14999) +- Formatting get lost and edit a template XLSX file - @MarkBaker [CodePlex #13215](https://phpexcel.codeplex.com/workitem/13215) +- Excel 2007 Reader /writer lost fontcolor - @MarkBaker [CodePlex #14029](https://phpexcel.codeplex.com/workitem/14029) +- file that makes cells go black - @MarkBaker [CodePlex #13374](https://phpexcel.codeplex.com/workitem/13374) +- Minor patchfix for Excel2003XML Reader when XML is defined with a charset attribute - @MarkBaker +- PHPExcel_Worksheet->toArray() index problem - @MarkBaker [CodePlex #15089](https://phpexcel.codeplex.com/workitem/15089) +- Merge cells 'un-merge' when using an existing spreadsheet - @MarkBaker [CodePlex #15094](https://phpexcel.codeplex.com/workitem/15094) +- Worksheet fromArray() only working with 2-D arrays - @MarkBaker [CodePlex #15129](https://phpexcel.codeplex.com/workitem/15129) +- rangeToarray function modified for non-existent cells - @xkeshav [CodePlex #15172](https://phpexcel.codeplex.com/workitem/15172) +- Images not getting copyied with the ->clone function - @MarkBaker [CodePlex #14980](https://phpexcel.codeplex.com/workitem/14980) +- AdvancedValueBinder.php: String sometimes becomes a date when it shouldn't - @MarkBaker [CodePlex #11576](https://phpexcel.codeplex.com/workitem/11576) +- Fix Excel5 Writer so that it only writes column dimensions for columns that are actually used rather than the full range (A to IV) - @MarkBaker +- FreezePane causing damaged or modified error - @MarkBaker [CodePlex #15198](https://phpexcel.codeplex.com/workitem/15198) + - The freezePaneByColumnAndRow() method row argument should default to 1 rather than 0. + - Default row argument for all __ByColumnAndRow() methods should be 1- Column reference rather than cell reference in Print Area definition - @MarkBaker [CodePlex #15121](https://phpexcel.codeplex.com/workitem/15121) + - Fix Excel2007 Writer to handle print areas that are defined as row or column ranges rather than just as cell ranges- Reduced false positives from isDateTimeFormatCode() method by suppressing testing within quoted strings - @MarkBaker +- Caching and tmp partition exhaustion - @MarkBaker [CodePlex #15312](https://phpexcel.codeplex.com/workitem/15312) +- Writing to Variable No Longer Works. $_tmp_dir Missing in PHPExcel\PHPExcel\Shared\OLE\PPS\Root.php - @MarkBaker [CodePlex #15308](https://phpexcel.codeplex.com/workitem/15308) +- Named ranges with dot don't get parsed properly - @MarkBaker [CodePlex #15379](https://phpexcel.codeplex.com/workitem/15379) +- insertNewRowBefore fails to consistently update references - @MarkBaker [CodePlex #15096](https://phpexcel.codeplex.com/workitem/15096) +- "i" is not a valid character for Excel date format masks (in isDateTimeFormatCode() method) - @MarkBaker +- PHPExcel_ReferenceHelper::insertNewBefore() is missing an 'Update worksheet: comments' section - @MKunert [CodePlex #15421](https://phpexcel.codeplex.com/workitem/15421) + +### General + +- Full column/row references in named ranges not supported by updateCellReference() - @MarkBaker [CodePlex #15409](https://phpexcel.codeplex.com/workitem/15409) +- Improved performance (speed), for building the Shared Strings table in the Excel2007 Writer. - @MarkBaker +- Improved performance (speed), for PHP to Excel date conversions - @MarkBaker +- Enhanced SheetViews element structures in the Excel2007 Writer for frozen panes. - @MarkBaker +- Removed Serialized Reader/Writer as these no longer work. - @MarkBaker + +## [1.7.5] - 2010-12-10 + +### Features + +- Implement Gnumeric File Format - @MarkBaker [CodePlex #8769](https://phpexcel.codeplex.com/workitem/8769) + - Initial work on Gnumeric Reader (Worksheet Data, Document Properties and basic Formatting)- Support for Extended Workbook Properties in Excel2007, Excel5 and OOCalc Readers; support for User-defined Workbook Properties in Excel2007 and OOCalc Readers - @MarkBaker +- Support for Extended and User-defined Workbook Properties in Excel2007 Writer - @MarkBaker +- Provided a setGenerateSheetNavigationBlock(false); option to suppress generation of the sheet navigation block when writing multiple worksheets to HTML - @MarkBaker +- Advanced Value Binder now recognises TRUE/FALSE strings (locale-specific) and converts to boolean - @MarkBaker +- PHPExcel_Worksheet->toArray() is returning truncated values - @MarkBaker [CodePlex #14301](https://phpexcel.codeplex.com/workitem/14301) +- Configure PDF Writer margins based on Excel Worksheet Margin Settings value - @MarkBaker +- Added Contiguous flag for the CSV Reader, when working with Read Filters - @MarkBaker +- Added getFormattedValue() method for cell object - @MarkBaker +- Added strictNullComparison argument to the worksheet fromArray() method - @MarkBaker + +### Bugfixes + +- Fix to toFormattedString() method in PHPExcel_Style_NumberFormat to handle fractions with a # code for the integer part - @MarkBaker +- NA() doesn't propagate in matrix calc - quick fix in JAMA/Matrix.php - @MarkBaker [CodePlex #14143](https://phpexcel.codeplex.com/workitem/14143) +- Excel5 : Formula : String constant containing double quotation mark - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Excel5 : Formula : Percent - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Excel5 : Formula : Error constant - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Excel5 : Formula : Concatenation operator - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Worksheet clone broken for CachedObjectStorage_Memory - @MarkBaker [CodePlex #14146](https://phpexcel.codeplex.com/workitem/14146) +- PHPExcel_Reader_Excel2007 fails when gradient fill without type is present in a file - @MarkBaker [CodePlex #12998](https://phpexcel.codeplex.com/workitem/12998) +- @ format for numeric strings in XLSX to CSV conversion - @MarkBaker [CodePlex #14176](https://phpexcel.codeplex.com/workitem/14176) +- Advanced Value Binder Not Working? - @MarkBaker [CodePlex #14223](https://phpexcel.codeplex.com/workitem/14223) +- unassigned object variable in PHPExcel->removeCellXfByIndex - @MarkBaker [CodePlex #14226](https://phpexcel.codeplex.com/workitem/14226) +- problem with getting cell values from another worksheet... (if cell doesn't exist) - @MarkBaker [CodePlex #14236](https://phpexcel.codeplex.com/workitem/14236) +- Setting cell values to one char strings & Trouble reading one character string (thanks gorfou) - @MarkBaker +- Worksheet title exception when duplicate worksheet is being renamed but exceeds the 31 character limit - @MarkBaker [CodePlex #14256](https://phpexcel.codeplex.com/workitem/14256) +- Named range with sheet name that contains the $ throws exception when getting the cell - @MarkBaker [CodePlex #14086](https://phpexcel.codeplex.com/workitem/14086) +- Added autoloader to DefaultValueBinder and AdvancedValueBinder - @MarkBaker +- Modified PHPExcel_Shared_Date::isDateTimeFormatCode() to return false if format code begins with "_" or with "0 " to prevent false positives - @MarkBaker + - These leading characters are most commonly associated with number, currency or accounting (or occasionally fraction) formats- BUG : Excel5 and setReadFilter ? - @MarkBaker [CodePlex #14374](https://phpexcel.codeplex.com/workitem/14374) +- Wrong exception message while deleting column - @MarkBaker [CodePlex #14425](https://phpexcel.codeplex.com/workitem/14425) +- Formula evaluation fails with Japanese sheet refs - @MarkBaker [CodePlex #14679](https://phpexcel.codeplex.com/workitem/14679) +- PHPExcel_Writer_PDF does not handle cell borders correctly - @MarkBaker [CodePlex #13559](https://phpexcel.codeplex.com/workitem/13559) +- Style : applyFromArray() for 'allborders' not working - @MarkBaker [CodePlex #14831](https://phpexcel.codeplex.com/workitem/14831) + +### General + +- Using $this when not in object context in Excel5 Reader - @MarkBaker [CodePlex #14837](https://phpexcel.codeplex.com/workitem/14837) +- Removes a unnecessary loop through each cell when applying conditional formatting to a range. - @MarkBaker +- Removed spurious PHP end tags (?>) - @MarkBaker +- Improved performance (speed) and reduced memory overheads, particularly for the Writers, but across the whole library. - @MarkBaker + +## [1.7.4] - 2010-08-26 + +### Bugfixes + +- Excel5 : Formula : Power - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Excel5 : Formula : Unary plus - @Progi1984 [CodePlex #7895](https://phpexcel.codeplex.com/workitem/7895) +- Excel5 : Just write the Escher stream if necessary in Worksheet - @Progi1984 +- Syntax errors in memcache.php 1.7.3c - @MarkBaker [CodePlex #13433](https://phpexcel.codeplex.com/workitem/13433) +- Support for row or column ranges in the calculation engine, e.g. =SUM(C:C) or =SUM(1:2) - @MarkBaker + - Also support in the calculation engine for absolute row or column ranges e.g. =SUM($C:$E) or =SUM($3:5)- Picture problem with Excel 2003 - @Erik Tilt [CodePlex #13455](https://phpexcel.codeplex.com/workitem/13455) +- Wrong variable used in addExternalSheet in PHPExcel.php - @MarkBaker [CodePlex #13484](https://phpexcel.codeplex.com/workitem/13484) +- "Invalid cell coordinate" error when formula access data from an other sheet - @MarkBaker [CodePlex #13515](https://phpexcel.codeplex.com/workitem/13515) +- (related to Work item 13515) Calculation engine confusing cell range worksheet when referencing cells in a different worksheet to the formula - @MarkBaker +- Wrong var naming in Worksheet->garbageCollect() - @MarkBaker [CodePlex #13752](https://phpexcel.codeplex.com/workitem/13752) +- PHPExcel_Style_*::__clone() methods cause cloning loops? - @MarkBaker [CodePlex #13764](https://phpexcel.codeplex.com/workitem/13764) +- Recent builds causing problems loading xlsx files? (ZipArchive issue?) - @MarkBaker [CodePlex #11488](https://phpexcel.codeplex.com/workitem/11488) +- cache_to_apc causes fatal error when processing large data sets - @MarkBaker [CodePlex #13856](https://phpexcel.codeplex.com/workitem/13856) +- OOCalc reader misses first line if it's a 'table-header-row' - @MarkBaker [CodePlex #13880](https://phpexcel.codeplex.com/workitem/13880) +- using cache with copy or clone bug? - @MarkBaker [CodePlex #14011](https://phpexcel.codeplex.com/workitem/14011) + - Fixed $worksheet->copy() or clone $worksheet when using cache_in_memory, cache_in_memory_gzip, cache_in_memory_serialized, cache_to_discISAM, cache_to_phpTemp, cache_to_apc and cache_to_memcache; + - Fixed but untested when using cache_to_wincache. +### Features + +- Standard Deviation functions returning DIV/0 Error when Standard Deviation is zero - @MarkBaker [CodePlex #13450](https://phpexcel.codeplex.com/workitem/13450) +- Support for print area with several ranges in the Excel2007 reader, and improved features for editing print area with several ranges - @MarkBaker +- Improved Cell Exception Reporting - @MarkBaker [CodePlex #13769](https://phpexcel.codeplex.com/workitem/13769) + +### General + +- Fixed problems with reading Excel2007 Properties - @MarkBaker +- PHP Strict Standards: Non-static method PHPExcel_Shared_String::utf16_decode() should not be called statically - @MarkBaker +- Array functions were ignored when loading an existing file containing them, and as a result, they would lose their 'cse' status. - @MarkBaker +- Minor memory tweaks to Excel2007 Writer - @MarkBaker +- Modified ReferenceHelper updateFormulaReferences() method to handle updates to row and column cell ranges (including absolute references e.g. =SUM(A:$E) or =SUM($5:5), and range/cell references that reference a worksheet by name), and to provide both performance and memory improvements. - @MarkBaker +- Modified Excel2007 Reader so that ReferenceHelper class is instantiated only once rather than for every shared formula in a workbook. - @MarkBaker +- Correct handling for additional (synonym) formula tokens in Excel5 Reader - @MarkBaker +- Additional reading of some Excel2007 Extended Properties (Company, Manager) - @MarkBaker + +## [1.7.3c] - 2010-06-01 + +### Bugfixes + +- Fatal error: Class 'ZipArchive' not found... ...Reader/Excel2007.php on line 217 - @MarkBaker [CodePlex #13012](https://phpexcel.codeplex.com/workitem/13012) +- PHPExcel_Writer_Excel2007 error after 1.7.3b - @MarkBaker [CodePlex #13398](https://phpexcel.codeplex.com/workitem/13398) + +## [1.7.3b] - 2010-05-31 + +### Bugfixes + +- Infinite loop when reading - @MarkBaker [CodePlex #12903](https://phpexcel.codeplex.com/workitem/12903) +- Wrong method chaining on PHPExcel_Worksheet class - @MarkBaker [CodePlex #13381](https://phpexcel.codeplex.com/workitem/13381) + +## [1.7.3] - 2010-05-17 + +### General + +- Applied patch 4990 (modified) - @Erik Tilt +- Applied patch 5568 (modified) - @MarkBaker +- Applied patch 5943 - @MarkBaker +- Upgrade build script to use Phing - @MarkBaker [CodePlex #13042](https://phpexcel.codeplex.com/workitem/13042) +- Replacing var with public/private - @Erik Tilt [CodePlex #11586](https://phpexcel.codeplex.com/workitem/11586) +- Applied Anthony's Sterling's Class Autoloader to reduce memory overhead by "Lazy Loading" of classes - @MarkBaker +- Modification to functions that accept a date parameter to support string values containing ordinals as per Excel (English language only) - @MarkBaker +- Modify PHPExcel_Style_NumberFormat::toFormattedString() to handle dates that fall outside of PHP's 32-bit date range - @MarkBaker +- Applied patch 5207 - @MarkBaker + +### Features + +- PHPExcel developer documentation: Set page margins - @Erik Tilt [CodePlex #11970](https://phpexcel.codeplex.com/workitem/11970) +- Special characters and accents in SYLK reader - @Erik Tilt [CodePlex #11038](https://phpexcel.codeplex.com/workitem/11038) +- Implement more Excel calculation functions - @MarkBaker + - Implemented the COUPDAYS(), COUPDAYBS(), COUPDAYSNC(), COUPNCD(), COUPPCD() and PRICE() Financial functions + - Implemented the N() and TYPE() Information functions + - Implemented the HYPERLINK() Lookup and Reference function- Horizontal page break support in PHPExcel_Writer_PDF - @Erik Tilt [CodePlex #11526](https://phpexcel.codeplex.com/workitem/11526) +- Introduce method setActiveSheetIndexByName() - @Erik Tilt [CodePlex #11529](https://phpexcel.codeplex.com/workitem/11529) +- AdvancedValueBinder.php: Automatically wrap text when there is new line in string (ALT+"Enter") - @Erik Tilt [CodePlex #11550](https://phpexcel.codeplex.com/workitem/11550) +- Data validation support in PHPExcel_Reader_Excel5 and PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10300](https://phpexcel.codeplex.com/workitem/10300) +- Improve autosize calculation - @MarkBaker [CodePlex #11616](https://phpexcel.codeplex.com/workitem/11616) +- Methods to translate locale-specific function names in formulae - @MarkBaker + - Language implementations for Czech (cs), Danish (da), German (de), English (uk), Spanish (es), Finnish (fi), French (fr), Hungarian (hu), Italian (it), Dutch (nl), Norwegian (no), Polish (pl), Portuguese (pt), Brazilian Portuguese (pt_br), Russian (ru) and Swedish (sv)- Implement document properties in Excel5 reader/writer - @Erik Tilt [CodePlex #9759](https://phpexcel.codeplex.com/workitem/9759) + - Fixed so far for PHPExcel_Reader_Excel5- Show/hide row and column headers in worksheet - @Erik Tilt [CodePlex #11849](https://phpexcel.codeplex.com/workitem/11849) +- Can't set font on writing PDF (by key) - @Erik Tilt [CodePlex #11919](https://phpexcel.codeplex.com/workitem/11919) +- Thousands scale (1000^n) support in PHPExcel_Style_NumberFormat::toFormattedString - @Erik Tilt [CodePlex #12096](https://phpexcel.codeplex.com/workitem/12096) +- Implement repeating rows in PDF and HTML writer - @Erik Tilt +- Sheet tabs in PHPExcel_Writer_HTML - @Erik Tilt [CodePlex #12289](https://phpexcel.codeplex.com/workitem/12289) +- Add Wincache CachedObjectProvider - @MarkBaker [CodePlex #13041](https://phpexcel.codeplex.com/workitem/13041) +- Configure PDF Writer paper size based on Excel Page Settings value, and provided methods to override paper size and page orientation with the writer - @MarkBaker + - Note PHPExcel defaults to Letter size, while the previous PDF writer enforced A4 size, so PDF writer will now default to Letter- Initial implementation of cell caching: allowing larger workbooks to be managed, but at a cost in speed - @MarkBaker + +### Bugfixes + +- Added an identify() method to the IO Factory that identifies the reader which will be used to load a particular file without actually loading it. - @MarkBaker +- Warning messages with INDEX function having 2 arguments - @MarkBaker [CodePlex #10979](https://phpexcel.codeplex.com/workitem/10979) +- setValue('=') should result in string instead of formula - @Erik Tilt [CodePlex #11473](https://phpexcel.codeplex.com/workitem/11473) +- method _raiseFormulaError should no be private - @MarkBaker [CodePlex #11471](https://phpexcel.codeplex.com/workitem/11471) +- Fatal error: Call to undefined function mb_substr() in ...Classes\PHPExcel\Reader\Excel5.php on line 2903 - @Erik Tilt [CodePlex #11485](https://phpexcel.codeplex.com/workitem/11485) +- getBold(), getItallic(), getStrikeThrough() not always working with PHPExcel_Reader_Excel2007 - @Erik Tilt [CodePlex #11487](https://phpexcel.codeplex.com/workitem/11487) +- AdvancedValueBinder.php not working correctly for $cell->setValue('hh:mm:ss') - @Erik Tilt [CodePlex #11492](https://phpexcel.codeplex.com/workitem/11492) +- Fixed leap year handling for the YEARFRAC() Date/Time function when basis ia 1 (Actual/actual) - @MarkBaker +- Warning messages - @MarkBaker [CodePlex #11490](https://phpexcel.codeplex.com/workitem/11490) + - Calculation Engine code modified to enforce strict standards for pass by reference- PHPExcel_Cell_AdvancedValueBinder doesnt work for dates in far future - @Erik Tilt [CodePlex #11483](https://phpexcel.codeplex.com/workitem/11483) +- MSODRAWING bug with long CONTINUE record in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #11528](https://phpexcel.codeplex.com/workitem/11528) +- PHPExcel_Reader_Excel2007 reads print titles as named range when there is more than one sheet - @Erik Tilt [CodePlex #11571](https://phpexcel.codeplex.com/workitem/11571) +- missing @return in phpdocblock in reader classes - @Erik Tilt [CodePlex #11561](https://phpexcel.codeplex.com/workitem/11561) +- AdvancedValueBinder.php: String sometimes becomes a date when it shouldn't - @Erik Tilt [CodePlex #11576](https://phpexcel.codeplex.com/workitem/11576) +- Small numbers escape treatment in PHPExcel_Style_NumberFormat::toFormattedString() - @Erik Tilt [CodePlex #11588](https://phpexcel.codeplex.com/workitem/11588) +- Blank styled cells are not blank in output by HTML writer due to   - @Erik Tilt [CodePlex #11590](https://phpexcel.codeplex.com/workitem/11590) +- Calculation engine bug: Existing, blank cell + number gives #NUM - @MarkBaker [CodePlex #11587](https://phpexcel.codeplex.com/workitem/11587) +- AutoSize only measures length of first line in cell with multiple lines (ALT+Enter) - @Erik Tilt [CodePlex #11608](https://phpexcel.codeplex.com/workitem/11608) +- Fatal error running Tests/12serializedfileformat.php (PHPExcel 1.7.2) - @Erik Tilt [CodePlex #11608](https://phpexcel.codeplex.com/workitem/11608) +- Fixed various errors in the WORKDAY() and NETWORKDAYS() Date/Time functions (particularly related to holidays) - @MarkBaker +- Uncaught exception 'Exception' with message 'Valid scale is between 10 and 400.' in Classes/PHPExcel/Worksheet/SheetView.php:115 - @Erik Tilt [CodePlex #11660](https://phpexcel.codeplex.com/workitem/11660) +- "Unrecognized token 39 in formula" with PHPExcel_Reader_Excel5 (occuring with add-in functions) - @Erik Tilt [CodePlex #11551](https://phpexcel.codeplex.com/workitem/11551) +- Excel2007 reader not reading PHPExcel_Style_Conditional::CONDITION_EXPRESSION - @Erik Tilt [CodePlex #11668](https://phpexcel.codeplex.com/workitem/11668) +- Fix to the BESSELI(), BESSELJ(), BESSELK(), BESSELY() and COMPLEX() Engineering functions to use correct default values for parameters - @MarkBaker +- DATEVALUE function not working for pure time values + allow DATEVALUE() function to handle partial dates (e.g. "1-Jun" or "12/2010") - @MarkBaker [CodePlex #11525](https://phpexcel.codeplex.com/workitem/11525) +- Fix for empty quoted strings in formulae - @MarkBaker +- Trap for division by zero in Bessel functions - @MarkBaker +- Fix to OOCalc Reader to convert semi-colon (;) argument separator in formulae to a comma (,) - @MarkBaker +- PHPExcel_Writer_Excel5_Parser cannot parse formula like =SUM(C$5:C5) - @Erik Tilt [CodePlex #11693](https://phpexcel.codeplex.com/workitem/11693) +- Fix to OOCalc Reader to handle dates that fall outside 32-bit PHP's date range - @MarkBaker +- File->sys_get_temp_dir() can fail in safe mode - @Erik Tilt [CodePlex #11692](https://phpexcel.codeplex.com/workitem/11692) +- Sheet references in Excel5 writer do not work when referenced sheet title contains non-Latin symbols - @Erik Tilt [CodePlex #11727](https://phpexcel.codeplex.com/workitem/11727) +- Bug in HTML writer can result in missing rows in output - @Erik Tilt [CodePlex #11743](https://phpexcel.codeplex.com/workitem/11743) +- setShowGridLines(true) not working with PHPExcel_Writer_PDF - @Erik Tilt [CodePlex #11674](https://phpexcel.codeplex.com/workitem/11674) +- PHPExcel_Worksheet_RowIterator initial position incorrect - @Erik Tilt [CodePlex #11836](https://phpexcel.codeplex.com/workitem/11836) +- PHPExcel_Worksheet_HeaderFooterDrawing Strict Exception thrown (by jshaw86) - @Erik Tilt [CodePlex #11835](https://phpexcel.codeplex.com/workitem/11835) +- Parts of worksheet lost when there are embedded charts (Excel5 reader) - @Erik Tilt [CodePlex #11850](https://phpexcel.codeplex.com/workitem/11850) +- VLOOKUP() function error when lookup value is passed as a cell reference rather than an absolute value - @MarkBaker +- First segment of Rich-Text not read correctly by PHPExcel_Reader_Excel2007 - @Erik Tilt [CodePlex #12041](https://phpexcel.codeplex.com/workitem/12041) +- Fatal Error with getCell('name') when name matches the pattern for a cell reference - @MarkBaker [CodePlex #12048](https://phpexcel.codeplex.com/workitem/12048) +- excel5 writer appears to be swapping image locations - @Erik Tilt [CodePlex #12039](https://phpexcel.codeplex.com/workitem/12039) +- Undefined index: host in ZipStreamWrapper.php, line 94 and line 101 - @Erik Tilt [CodePlex #11954](https://phpexcel.codeplex.com/workitem/11954) +- BIFF8 File Format problem (too short COLINFO record) - @Erik Tilt [CodePlex #11672](https://phpexcel.codeplex.com/workitem/11672) +- Column width sometimes changed after read/write with Excel2007 reader/writer - @Erik Tilt [CodePlex #12121](https://phpexcel.codeplex.com/workitem/12121) +- Worksheet.php throws a fatal error when styling is turned off via setReadDataOnly on the reader - @Erik Tilt [CodePlex #11964](https://phpexcel.codeplex.com/workitem/11964) +- Checking for Circular References in Formulae - @MarkBaker [CodePlex #11851](https://phpexcel.codeplex.com/workitem/11851) + - Calculation Engine code now traps for cyclic references, raising an error or throwing an exception, or allows 1 or more iterations through cyclic references, based on a configuration setting- PNG transparency using Excel2007 writer - @Erik Tilt [CodePlex #12244](https://phpexcel.codeplex.com/workitem/12244) +- Custom readfilter error when cell formulas reference excluded cells (Excel5 reader) - @Erik Tilt [CodePlex #12221](https://phpexcel.codeplex.com/workitem/12221) +- Protection problem in XLS - @Erik Tilt [CodePlex #12288](https://phpexcel.codeplex.com/workitem/12288) +- getColumnDimension()->setAutoSize() incorrect on cells with Number Formatting - @Erik Tilt [CodePlex #12300](https://phpexcel.codeplex.com/workitem/12300) +- Notices reading Excel file with Add-in funcitons (PHPExcel_Reader_Excel5) - @Erik Tilt [CodePlex #12378](https://phpexcel.codeplex.com/workitem/12378) +- Excel5 reader not reading formulas with deleted sheet references - @Erik Tilt [CodePlex #12380](https://phpexcel.codeplex.com/workitem/12380) +- Named range (defined name) scope problems for in PHPExcel - @Erik Tilt [CodePlex #12404](https://phpexcel.codeplex.com/workitem/12404) +- PHP Parse error: syntax error, unexpected T_PUBLIC in PHPExcel/Calculation.php on line 3482 - @Erik Tilt [CodePlex #12423](https://phpexcel.codeplex.com/workitem/12423) +- Named ranges don't appear in name box using Excel5 writer - @Erik Tilt [CodePlex #12505](https://phpexcel.codeplex.com/workitem/12505) +- Many merged cells + autoSize column -> slows down the writer - @Erik Tilt [CodePlex #12509](https://phpexcel.codeplex.com/workitem/12509) +- Incorrect fallback order comment in Shared/Strings.php ConvertEncoding() - @Erik Tilt [CodePlex #12539](https://phpexcel.codeplex.com/workitem/12539) +- IBM AIX iconv() will not work, should revert to mbstring etc. instead - @Erik Tilt [CodePlex #12538](https://phpexcel.codeplex.com/workitem/12538) +- Excel5 writer and mbstring functions overload - @Erik Tilt [CodePlex #12568](https://phpexcel.codeplex.com/workitem/12568) +- OFFSET needs to flattenSingleValue the $rows and $columns args - @MarkBaker [CodePlex #12672](https://phpexcel.codeplex.com/workitem/12672) +- Formula with DMAX(): Notice: Undefined offset: 2 in ...\PHPExcel\Calculation.php on line 2365 - @MarkBaker [CodePlex #12546](https://phpexcel.codeplex.com/workitem/12546) + - Note that the Database functions have not yet been implemented- Call to a member function getParent() on a non-object in Classes\\PHPExcel\\Calculation.php Title is required - @MarkBaker [CodePlex #12839](https://phpexcel.codeplex.com/workitem/12839) +- Cyclic Reference in Formula - @MarkBaker [CodePlex #12935](https://phpexcel.codeplex.com/workitem/12935) +- Memory error...data validation? - @MarkBaker [CodePlex #13025](https://phpexcel.codeplex.com/workitem/13025) + +## [1.7.2] - 2010-01-11 + +### General + +- Applied patch 4362 - @Erik Tilt +- Applied patch 4363 (modified) - @Erik Tilt +- 1.7.1 Extremely Slow - Refactored PHPExcel_Calculation_Functions::flattenArray() method and set calculation cache timer default to 2.5 seconds - @MarkBaker [CodePlex #10874](https://phpexcel.codeplex.com/workitem/10874) +- Allow formulae to contain line breaks - @MarkBaker +- split() function deprecated in PHP 5.3.0 - @Erik Tilt [CodePlex #10910](https://phpexcel.codeplex.com/workitem/10910) +- sys_get_temp_dir() requires PHP 5.2.1, not PHP 5.2 [provide fallback function for PHP 5.2.0] - @Erik Tilt +- Implementation of the ISPMT() Financial function by Matt Groves - @MarkBaker +- Put the example of formula with more arguments in documentation - @MarkBaker [CodePlex #11052](https://phpexcel.codeplex.com/workitem/11052) + +### Features + +- Improved accuracy for the GAMMAINV() Statistical Function - @MarkBaker +- XFEXT record support to fix colors change from Excel5 reader, and copy/paste color change with Excel5 writer - @Erik Tilt [CodePlex #10409](https://phpexcel.codeplex.com/workitem/10409) + - Excel5 reader reads RGB color information in XFEXT records for borders, font color and fill color- Implement more Excel calculation functions - @MarkBaker + - Implemented the FVSCHEDULE(), XNPV(), IRR(), MIRR(), XIRR() and RATE() Financial functions + - Implemented the SUMPRODUCT() Mathematical function + - Implemented the ZTEST() Statistical Function- Multiple print areas in one sheet - @Erik Tilt [CodePlex #10919](https://phpexcel.codeplex.com/workitem/10919) +- Store calculated values in output by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10930](https://phpexcel.codeplex.com/workitem/10930) +- Sheet protection options in Excel5 reader/writer - @Erik Tilt [CodePlex #10939](https://phpexcel.codeplex.com/workitem/10939) +- Modification of the COUNT(), AVERAGE(), AVERAGEA(), DEVSQ, AVEDEV(), STDEV(), STDEVA(), STDEVP(), STDEVPA(), VARA() and VARPA() SKEW() and KURT() functions to correctly handle boolean values depending on whether they're passed in as values, values within a matrix or values within a range of cells. - @MarkBaker +- Cell range selection - @Erik Tilt +- Root-relative path handling - @MarkBaker [CodePlex #10266](https://phpexcel.codeplex.com/workitem/10266) + +### Bugfixes + +- Named Ranges not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #11315](https://phpexcel.codeplex.com/workitem/11315) +- Excel2007 Reader fails to load Apache POI generated Excel - @MarkBaker [CodePlex #11206](https://phpexcel.codeplex.com/workitem/11206) +- Number format is broken when system's thousands separator is empty - @MarkBaker [CodePlex #11154](https://phpexcel.codeplex.com/workitem/11154) +- ReferenceHelper::updateNamedFormulas throws errors if oldName is empty - @MarkBaker [CodePlex #11401](https://phpexcel.codeplex.com/workitem/11401) +- parse_url() fails to parse path to an image in xlsx - @MarkBaker [CodePlex #11296](https://phpexcel.codeplex.com/workitem/11296) +- Workaround for iconv_substr() bug in PHP 5.2.0 - @Erik Tilt [CodePlex #10876](https://phpexcel.codeplex.com/workitem/10876) +- 1 pixel error for image width and height with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10877](https://phpexcel.codeplex.com/workitem/10877) +- Fix to GEOMEAN() Statistical function - @MarkBaker +- setValue('-') and setValue('.') sets numeric 0 instead of 1-character string - @Erik Tilt [CodePlex #10884](https://phpexcel.codeplex.com/workitem/10884) +- Row height sometimes much too low after read with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10885](https://phpexcel.codeplex.com/workitem/10885) +- Diagonal border. Miscellaneous missing support. - @Erik Tilt [CodePlex #10888](https://phpexcel.codeplex.com/workitem/10888) + - Constant PHPExcel_Style_Borders::DIAGONAL_BOTH added to support double-diagonal (cross) + - PHPExcel_Reader_Excel2007 not always reading diagonal borders (only recognizes 'true' and not '1') + - PHPExcel_Reader_Excel5 support for diagonal borders + - PHPExcel_Writer_Excel5 support for diagonal borders- Session bug: Fatal error: Call to a member function bindValue() on a non-object in ...\Classes\PHPExcel\Cell.php on line 217 - @Erik Tilt [CodePlex #10894](https://phpexcel.codeplex.com/workitem/10894) +- Colors messed up saving twice with same instance of PHPExcel_Writer_Excel5 (regression since 1.7.0) - @Erik Tilt [CodePlex #10896](https://phpexcel.codeplex.com/workitem/10896) +- Method PHPExcel_Worksheet::setDefaultStyle is not working - @Erik Tilt [CodePlex #10917](https://phpexcel.codeplex.com/workitem/10917) +- PHPExcel_Reader_CSV::canRead() sometimes says false when it shouldn't - @Erik Tilt [CodePlex #10897](https://phpexcel.codeplex.com/workitem/10897) +- Changes in workbook not picked up between two saves with PHPExcel_Writer_Excel2007 - @Erik Tilt [CodePlex #10922](https://phpexcel.codeplex.com/workitem/10922) +- Decimal and thousands separators missing in HTML and PDF output - @Erik Tilt [CodePlex #10913](https://phpexcel.codeplex.com/workitem/10913) +- Notices with PHPExcel_Reader_Excel5 and named array constants - @Erik Tilt [CodePlex #10936](https://phpexcel.codeplex.com/workitem/10936) +- Calculation engine limitation on 32-bit platform with integers > 2147483647 - @MarkBaker [CodePlex #10938](https://phpexcel.codeplex.com/workitem/10938) +- Shared(?) formulae containing absolute cell references not read correctly using Excel5 Reader - @Erik Tilt [CodePlex #10959](https://phpexcel.codeplex.com/workitem/10959) +- Warning messages with intersection operator involving single cell - @MarkBaker [CodePlex #10962](https://phpexcel.codeplex.com/workitem/10962) +- Infinite loop in Excel5 reader caused by zero-length string in SST - @Erik Tilt [CodePlex #10980](https://phpexcel.codeplex.com/workitem/10980) +- Remove unnecessary cell sorting to improve speed by approx. 18% in HTML and PDF writers - @Erik Tilt [CodePlex #10983](https://phpexcel.codeplex.com/workitem/10983) +- Cannot read A1 cell content - OO_Reader - @MarkBaker [CodePlex #10977](https://phpexcel.codeplex.com/workitem/10977) +- Transliteration failed, invalid encoding - @Erik Tilt [CodePlex #11000](https://phpexcel.codeplex.com/workitem/11000) + +## [1.7.1] - 2009-11-02 + +### General + +- ereg() function deprecated in PHP 5.3.0 - @Erik Tilt [CodePlex #10687](https://phpexcel.codeplex.com/workitem/10687) +- Writer Interface Inconsequence - setTempDir and setUseDiskCaching - @MarkBaker [CodePlex #10739](https://phpexcel.codeplex.com/workitem/10739) + +### Features + +- Upgrade to TCPDF 4.8.009 - @Erik Tilt +- Support for row and column styles (feature request) - @Erik Tilt + - Basic implementation for Excel2007/Excel5 reader/writer- Hyperlink to local file in Excel5 reader/writer - @Erik Tilt [CodePlex #10459](https://phpexcel.codeplex.com/workitem/10459) +- Color Tab (Color Sheet's name) - @MarkBaker [CodePlex #10472](https://phpexcel.codeplex.com/workitem/10472) +- Border style "double" support in PHPExcel_Writer_HTML - @Erik Tilt [CodePlex #10488](https://phpexcel.codeplex.com/workitem/10488) +- Multi-section number format support in HTML/PDF/CSV writers - @Erik Tilt [CodePlex #10492](https://phpexcel.codeplex.com/workitem/10492) +- Some additional performance tweaks in the calculation engine - @MarkBaker +- Fix result of DB() and DDB() Financial functions to 2dp when in Gnumeric Compatibility mode - @MarkBaker +- Added AMORDEGRC(), AMORLINC() and COUPNUM() Financial function (no validation of parameters yet) - @MarkBaker +- Improved accuracy of TBILLEQ(), TBILLPRICE() and TBILLYIELD() Financial functions when in Excel or Gnumeric mode - @MarkBaker +- Added INDIRECT() Lookup/Reference function (only supports full addresses at the moment) - @MarkBaker +- PHPExcel_Reader_CSV::canRead() improvements - @MarkBaker [CodePlex #10498](https://phpexcel.codeplex.com/workitem/10498) +- Input encoding option for PHPExcel_Reader_CSV - @Erik Tilt [CodePlex #10500](https://phpexcel.codeplex.com/workitem/10500) +- Colored number format support, e.g. [Red], in HTML/PDF output - @Erik Tilt [CodePlex #10493](https://phpexcel.codeplex.com/workitem/10493) +- Color Tab (Color Sheet's name) [Excel5 reader/writer support] - @Erik Tilt [CodePlex #10559](https://phpexcel.codeplex.com/workitem/10559) +- Initial version of SYLK (slk) and Excel 2003 XML Readers (Cell data and basic cell formatting) - @MarkBaker +- Initial version of Open Office Calc (ods) Reader (Cell data only) - @MarkBaker +- Initial use of "pass by reference" in the calculation engine for ROW() and COLUMN() Lookup/Reference functions - @MarkBaker +- COLUMNS() and ROWS() Lookup/Reference functions, and SUBSTITUTE() Text function - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- AdvancedValueBinder(): Re-enable zero-padded string-to-number conversion, e.g '0004' -> 4 - @Erik Tilt [CodePlex #10502](https://phpexcel.codeplex.com/workitem/10502) +- Make PHP type match Excel datatype - @Erik Tilt [CodePlex #10600](https://phpexcel.codeplex.com/workitem/10600) +- Change first page number on header - @MarkBaker [CodePlex #10630](https://phpexcel.codeplex.com/workitem/10630) +- Applied patch 3941 - @MarkBaker +- Hidden sheets - @MB,ET [CodePlex #10745](https://phpexcel.codeplex.com/workitem/10745) +- mbstring fallback when iconv is broken - @Erik Tilt [CodePlex #10761](https://phpexcel.codeplex.com/workitem/10761) +- Note, can't yet handle comparison of two matrices - @MarkBaker +- Improved handling for validation and error trapping in a number of functions - @MarkBaker +- Improved support for fraction number formatting - @MarkBaker +- Support Reading CSV with Byte Order Mark (BOM) - @Erik Tilt [CodePlex #10455](https://phpexcel.codeplex.com/workitem/10455) + +### Bugfixes + +- addExternalSheet() at specified index - @Erik Tilt [CodePlex #10860](https://phpexcel.codeplex.com/workitem/10860) +- Named range can no longer be passed to worksheet->getCell() - @MarkBaker [CodePlex #10684](https://phpexcel.codeplex.com/workitem/10684) +- RichText HTML entities no longer working in PHPExcel 1.7.0 - @Erik Tilt [CodePlex #10455](https://phpexcel.codeplex.com/workitem/10455) +- Fit-to-width value of 1 is lost after read/write of Excel2007 spreadsheet [+ support for simultaneous scale/fitToPage] - @Erik Tilt +- Performance issue identified by profiling - @MarkBaker [CodePlex #10469](https://phpexcel.codeplex.com/workitem/10469) +- setSelectedCell is wrong - @Erik Tilt [CodePlex #10473](https://phpexcel.codeplex.com/workitem/10473) +- Images get squeezed/stretched with (Mac) Verdana 10 Excel files using Excel5 reader/writer - @Erik Tilt [CodePlex #10481](https://phpexcel.codeplex.com/workitem/10481) +- Error in argument count for DATEDIF() function - @MarkBaker [CodePlex #10482](https://phpexcel.codeplex.com/workitem/10482) +- updateFormulaReferences is buggy - @MarkBaker [CodePlex #10452](https://phpexcel.codeplex.com/workitem/10452) +- CellIterator returns null Cell if onlyExistingCells is set and key() is in use - @MarkBaker [CodePlex #10485](https://phpexcel.codeplex.com/workitem/10485) +- Wrong RegEx for parsing cell references in formulas - @MarkBaker [CodePlex #10453](https://phpexcel.codeplex.com/workitem/10453) +- Optimisation subverted to devastating effect if IterateOnlyExistingCells is clear - @MarkBaker [CodePlex #10486](https://phpexcel.codeplex.com/workitem/10486) +- Fatal error: Uncaught exception 'Exception' with message 'Unrecognized token 6C in formula'... with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10494](https://phpexcel.codeplex.com/workitem/10494) +- Fractions stored as text are not treated as numbers by PHPExcel's calculation engine - @MarkBaker [CodePlex #10490](https://phpexcel.codeplex.com/workitem/10490) +- AutoFit (autosize) row height not working in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10503](https://phpexcel.codeplex.com/workitem/10503) +- Fixed problem with null values breaking the calculation stack - @MarkBaker +- Date number formats sometimes fail with PHPExcel_Style_NumberFormat::toFormattedString, e.g. [$-40047]mmmm d yyyy - @Erik Tilt [CodePlex #10524](https://phpexcel.codeplex.com/workitem/10524) +- Fixed minor problem with DATEDIFF YM calculation - @MarkBaker +- Applied patch 3695 - @MarkBaker +- setAutosize() and Date cells not working properly - @Erik Tilt [CodePlex #10536](https://phpexcel.codeplex.com/workitem/10536) +- Time value hour offset in output by HTML/PDF/CSV writers (system timezone problem) - @Erik Tilt [CodePlex #10556](https://phpexcel.codeplex.com/workitem/10556) +- Control characters 0x14-0x1F are not treated by PHPExcel - @Erik Tilt [CodePlex #10558](https://phpexcel.codeplex.com/workitem/10558) +- PHPExcel_Writer_Excel5 not working when open_basedir restriction is in effect - @Erik Tilt [CodePlex #10560](https://phpexcel.codeplex.com/workitem/10560) +- IF formula calculation problem in PHPExcel 1.7.0 (string comparisons) - @MarkBaker [CodePlex #10563](https://phpexcel.codeplex.com/workitem/10563) +- Improved CODE() Text function result for UTF-8 characters - @MarkBaker +- Empty rows are collapsed with HTML/PDF writer - @Erik Tilt [CodePlex #10568](https://phpexcel.codeplex.com/workitem/10568) +- Gaps between rows in output by PHPExcel_Writer_PDF (Upgrading to TCPDF 4.7.003) - @Erik Tilt [CodePlex #10569](https://phpexcel.codeplex.com/workitem/10569) +- Problem reading formulas (Excel5 reader problem with "fake" shared formulas) - @Erik Tilt [CodePlex #10575](https://phpexcel.codeplex.com/workitem/10575) +- Error type in formula: "_raiseFormulaError message is Formula Error: An unexpected error occured" - @MarkBaker [CodePlex #10588](https://phpexcel.codeplex.com/workitem/10588) +- Miscellaneous column width problems in Excel5/Excel2007 writer - @Erik Tilt [CodePlex #10599](https://phpexcel.codeplex.com/workitem/10599) +- Reader/Excel5 'Unrecognized token 2D in formula' in latest version - @Erik Tilt [CodePlex #10615](https://phpexcel.codeplex.com/workitem/10615) +- on php 5.3 PHPExcel 1.7 Excel 5 reader fails in _getNextToken, token = 2C, throws exception - @Erik Tilt [CodePlex #10623](https://phpexcel.codeplex.com/workitem/10623) +- Fatal error when altering styles after workbook has been saved - @Erik Tilt [CodePlex #10617](https://phpexcel.codeplex.com/workitem/10617) +- Images vertically stretched or squeezed when default font size is changed (PHPExcel_Writer_Excel5) - @Erik Tilt [CodePlex #10661](https://phpexcel.codeplex.com/workitem/10661) +- Styles not read in "manipulated" Excel2007 workbook - @Erik Tilt [CodePlex #10676](https://phpexcel.codeplex.com/workitem/10676) +- Windows 7 says corrupt file by PHPExcel_Writer_Excel5 when opening in Excel - @Erik Tilt [CodePlex #10059](https://phpexcel.codeplex.com/workitem/10059) +- Calculations sometimes not working with cell references to other sheets - @MarkBaker [CodePlex #10708](https://phpexcel.codeplex.com/workitem/10708) +- Problem with merged cells after insertNewRowBefore() - @Erik Tilt [CodePlex #10706](https://phpexcel.codeplex.com/workitem/10706) +- Applied patch 4023 - @MarkBaker +- Fix to SUMIF() and COUNTIF() Statistical functions for when condition is a match against a string value - @MarkBaker +- PHPExcel_Cell::coordinateFromString should throw exception for bad string parameter - @Erik Tilt [CodePlex #10721](https://phpexcel.codeplex.com/workitem/10721) +- EucrosiaUPC (Thai font) not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10723](https://phpexcel.codeplex.com/workitem/10723) +- Improved the return of calculated results when the result value is an array - @MarkBaker +- Allow calculation engine to support Functions prefixed with @ within formulae - @MarkBaker +- Intersection operator (space operator) fatal error with calculation engine - @MarkBaker [CodePlex #10632](https://phpexcel.codeplex.com/workitem/10632) +- Chinese, Japanese, Korean characters show as squares in PDF - @Erik Tilt [CodePlex #10742](https://phpexcel.codeplex.com/workitem/10742) +- sheet title allows invalid characters - @Erik Tilt [CodePlex #10756](https://phpexcel.codeplex.com/workitem/10756) +- Sheet!$A$1 as function argument in formula causes infinite loop in Excel5 writer - @Erik Tilt [CodePlex #10757](https://phpexcel.codeplex.com/workitem/10757) +- Cell range involving name not working with calculation engine - Modified calculation parser to handle range operator (:), but doesn't currently handle worksheet references with spaces or other non-alphameric characters, or trap erroneous references - @MarkBaker [CodePlex #10740](https://phpexcel.codeplex.com/workitem/10740) +- DATE function problem with calculation engine (says too few arguments given) - @MarkBaker [CodePlex #10798](https://phpexcel.codeplex.com/workitem/10798) +- Blank cell can cause wrong calculated value - @MarkBaker [CodePlex #10799](https://phpexcel.codeplex.com/workitem/10799) +- Modified ROW() and COLUMN() Lookup/Reference Functions to return an array when passed a cell range, plus some additional work on INDEX() - @MarkBaker +- Images not showing in Excel 97 using PHPExcel_Writer_Excel5 (patch by Jordi Gutiérrez Hermoso) - @Erik Tilt [CodePlex #10817](https://phpexcel.codeplex.com/workitem/10817) +- When figures are contained in the excel sheet, Reader was stopped - @Erik Tilt [CodePlex #10785](https://phpexcel.codeplex.com/workitem/10785) +- Formulas changed after insertNewRowBefore() - @MarkBaker [CodePlex #10818](https://phpexcel.codeplex.com/workitem/10818) +- Cell range row offset problem with shared formulas using PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10825](https://phpexcel.codeplex.com/workitem/10825) +- Warning: Call-time pass-by-reference has been deprecated - @MarkBaker [CodePlex #10832](https://phpexcel.codeplex.com/workitem/10832) +- Image should "Move but don't size with cells" instead of "Move and size with cells" with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10849](https://phpexcel.codeplex.com/workitem/10849) +- Opening a Excel5 generated XLS in Excel 2007 results in header/footer entry not showing on input - @Erik Tilt [CodePlex #10856](https://phpexcel.codeplex.com/workitem/10856) +- addExternalSheet() not returning worksheet - @Erik Tilt [CodePlex #10859](https://phpexcel.codeplex.com/workitem/10859) +- Invalid results in formulas with named ranges - @MarkBaker [CodePlex #10629](https://phpexcel.codeplex.com/workitem/10629) + +## [1.7.0] - 2009-08-10 + +### General + +- Expand documentation: Number formats - @Erik Tilt +- Class 'PHPExcel_Cell_AdvancedValueBinder' not found - @Erik Tilt + +### Features + +- Change return type of date functions to PHPExcel_Calculation_Functions::RETURNDATE_EXCEL - @MarkBaker +- New RPN and stack-based calculation engine for improved performance of formula calculation - @MarkBaker + - Faster (anything between 2 and 12 times faster than the old parser, depending on the complexity and nature of the formula) + - Significantly more memory efficient when formulae reference cells across worksheets + - Correct behaviour when referencing Named Ranges that exist on several worksheets + - Support for Excel ^ (Exponential) and % (Percentage) operators + - Support for matrices within basic arithmetic formulae (e.g. ={1,2,3;4,5,6;7,8,9}/2) + - Better trapping/handling of NaN and infinity results (return #NUM! error) + - Improved handling of empty parameters for Excel functions + - Optional logging of calculation steps- New calculation engine can be accessed independently of workbooks (for use as a standalone calculator) - @MarkBaker +- Implement more Excel calculation functions - @MarkBaker + - Initial implementation of the COUNTIF() and SUMIF() Statistical functions + - Added ACCRINT() Financial function- Modifications to number format handling for dddd and ddd masks in dates, use of thousand separators even when locale only implements it for money, and basic fraction masks (0 ?/? and ?/?) - @MarkBaker +- Support arbitrary fixed number of decimals in PHPExcel_Style_NumberFormat::toFormattedString() - @Erik Tilt +- Improving performance and memory on data dumps - @Erik Tilt + - Various style optimizations (merging from branch wi6857-memory) + - Moving hyperlink and dataValidation properties from cell to worksheet for lower PHP memory usage- Provide fluent interfaces where possible - @MarkBaker +- Make easy way to apply a border to a rectangular selection - @Erik Tilt +- Support for system window colors in PHPExcel_Reader_Excel5 - @Erik Tilt +- Horizontal center across selection - @Erik Tilt +- Merged cells record, write to full record size in PHPExcel_Writer_Excel5 - @Erik Tilt +- Add page break between sheets in exported PDF - @MarkBaker +- Sanitization of UTF-8 input for cell values - @Erik Tilt +- Read cached calculated value with PHPExcel_Reader_Excel5 - @Erik Tilt +- Miscellaneous CSS improvements for PHPExcel_Writer_HTML - @Erik Tilt +- getProperties: setCompany feature request - @Erik Tilt +- Insert worksheet at a specified index - @MarkBaker +- Change worksheet index - @MarkBaker +- Readfilter for CSV reader - @MarkBaker +- Check value of mbstring.func_overload when saving with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10172](https://phpexcel.codeplex.com/workitem/10172) +- Eliminate dependency of an include path pointing to class directory - @Erik Tilt [CodePlex #10251](https://phpexcel.codeplex.com/workitem/10251) +- Method for getting the correct reader for a certain file (contribution) - @Erik Tilt [CodePlex #10292](https://phpexcel.codeplex.com/workitem/10292) +- Choosing specific row in fromArray method - @Erik Tilt [CodePlex #10287](https://phpexcel.codeplex.com/workitem/10287) +- Shared formula support in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10319](https://phpexcel.codeplex.com/workitem/10319) + +### Bugfixes + +- Right-to-left column direction in worksheet - @MB,ET [CodePlex #10345](https://phpexcel.codeplex.com/workitem/10345) +- PHPExcel_Reader_Excel5 not reading PHPExcel_Style_NumberFormat::FORMAT_NUMBER ('0') - @Erik Tilt +- Fractional row height in locale other than English results in corrupt output using PHPExcel_Writer_Excel2007 - @Erik Tilt +- Fractional (decimal) numbers not inserted correctly when locale is other than English - @Erik Tilt +- Fractional calculated value in locale other than English results in corrupt output using PHPExcel_Writer_Excel2007 - @Erik Tilt +- Locale aware decimal and thousands separator in exported formats HTML, CSV, PDF - @Erik Tilt +- Cannot Add Image with Space on its Name - @MarkBaker +- Black line at top of every page in output by PHPExcel_Writer_PDF - @Erik Tilt +- Border styles and border colors not showing in HTML output (regression since 1.6.4) - @Erik Tilt +- Hidden screen gridlines setting in worksheet not read by PHPExcel_Reader_Excel2007 - @Erik Tilt +- Some valid sheet names causes corrupt output using PHPExcel_Writer_Excel2007 - @MarkBaker +- More than 32,767 characters in a cell gives corrupt Excel file - @Erik Tilt +- Images not getting copyied with the ->copy() function - @Erik Tilt +- Bad calculation of column width setAutoSize(true) function - @Erik Tilt +- Dates are sometimes offset by 1 day in output by HTML and PDF writers depending on system timezone setting - @Erik Tilt +- Wingdings symbol fonts not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10003](https://phpexcel.codeplex.com/workitem/10003) +- White space string prefix stripped by PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #10010](https://phpexcel.codeplex.com/workitem/10010) +- The name of the Workbook stream MUST be "Workbook", not "Book" - @Erik Tilt [CodePlex #10023](https://phpexcel.codeplex.com/workitem/10023) +- Avoid message "Microsoft Excel recalculates formulas..." when closing xls file from Excel - @Erik Tilt [CodePlex #10030](https://phpexcel.codeplex.com/workitem/10030) +- Non-unique newline representation causes problems with LEN formula - @Erik Tilt [CodePlex #10031](https://phpexcel.codeplex.com/workitem/10031) +- Newline in cell not showing with PHPExcel_Writer_HTML and PHPExcel_Writer_PDF - @Erik Tilt [CodePlex #10033](https://phpexcel.codeplex.com/workitem/10033) +- Rich-Text strings get prefixed by   when output by HTML writer - @Erik Tilt [CodePlex #10046](https://phpexcel.codeplex.com/workitem/10046) +- Leading spaces do not appear in output by HTML/PDF writers - @Erik Tilt [CodePlex #10052](https://phpexcel.codeplex.com/workitem/10052) +- Empty Apache POI-generated file can not be read - @MarkBaker [CodePlex #10061](https://phpexcel.codeplex.com/workitem/10061) +- Column width not scaling correctly with font size in HTML and PDF writers - @Erik Tilt [CodePlex #10068](https://phpexcel.codeplex.com/workitem/10068) +- Inaccurate row heights with HTML writer - @Erik Tilt [CodePlex #10069](https://phpexcel.codeplex.com/workitem/10069) +- Reference helper - @MarkBaker +- Excel 5 Named ranges should not be local to the worksheet, but accessible from all worksheets - @MarkBaker +- Row heights are ignored by PHPExcel_Writer_PDF - @Erik Tilt [CodePlex #10088](https://phpexcel.codeplex.com/workitem/10088) +- Write raw XML - @MarkBaker +- removeRow(), removeColumn() not always clearing cell values - @Erik Tilt [CodePlex #10098](https://phpexcel.codeplex.com/workitem/10098) +- Problem reading certain hyperlink records with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10142](https://phpexcel.codeplex.com/workitem/10142) +- Hyperlink cell range read failure with PHPExcel_Reader_Excel2007 - @Erik Tilt [CodePlex #10143](https://phpexcel.codeplex.com/workitem/10143) +- 'Column string index can not be empty.' - @MarkBaker [CodePlex #10149](https://phpexcel.codeplex.com/workitem/10149) +- getHighestColumn() sometimes says there are 256 columns with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10204](https://phpexcel.codeplex.com/workitem/10204) +- extractSheetTitle fails when sheet title contains exclamation mark (!) - @Erik Tilt [CodePlex #10220](https://phpexcel.codeplex.com/workitem/10220) +- setTitle() sometimes erroneously appends integer to sheet name - @Erik Tilt [CodePlex #10221](https://phpexcel.codeplex.com/workitem/10221) +- Mac BIFF5 Excel file read failure (missing support for Mac OS Roman character set) - @Erik Tilt [CodePlex #10229](https://phpexcel.codeplex.com/workitem/10229) +- BIFF5 header and footer incorrectly read by PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10230](https://phpexcel.codeplex.com/workitem/10230) +- iconv notices when reading hyperlinks with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10259](https://phpexcel.codeplex.com/workitem/10259) +- Excel5 reader OLE read failure with small Mac BIFF5 Excel files - @Erik Tilt [CodePlex #10252](https://phpexcel.codeplex.com/workitem/10252) +- Problem in reading formula : IF( IF ) with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10272](https://phpexcel.codeplex.com/workitem/10272) +- Error reading formulas referencing external sheets with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10274](https://phpexcel.codeplex.com/workitem/10274) +- Image horizontally stretched when default font size is increased (PHPExcel_Writer_Excel5) - @Erik Tilt [CodePlex #10291](https://phpexcel.codeplex.com/workitem/10291) +- Undefined offset in Reader\Excel5.php on line 3572 - @Erik Tilt [CodePlex #10333](https://phpexcel.codeplex.com/workitem/10333) +- PDF output different then XLS (copied data) - @MarkBaker [CodePlex #10340](https://phpexcel.codeplex.com/workitem/10340) +- Internal hyperlinks with UTF-8 sheet names not working in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #10352](https://phpexcel.codeplex.com/workitem/10352) +- String shared formula result read error with PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #10361](https://phpexcel.codeplex.com/workitem/10361) +- Uncaught exception 'Exception' with message 'Valid scale is between 10 and 400.' in Classes/PHPExcel/Worksheet/PageSetup.php:338 - @Erik Tilt [CodePlex #10363](https://phpexcel.codeplex.com/workitem/10363) +- Using setLoadSheetsOnly fails if you do not use setReadDataOnly(true) and sheet is not the first sheet - @Erik Tilt [CodePlex #10355](https://phpexcel.codeplex.com/workitem/10355) +- getCalculatedValue() sometimes incorrect with IF formula and 0-values - @MarkBaker [CodePlex #10362](https://phpexcel.codeplex.com/workitem/10362) +- Excel Reader 2007 problem with "shared" formulae when "master" is an error - @MarkBaker +- Named Range Bug, using the same range name on different worksheets - @MarkBaker +- Java code in JAMA classes - @MarkBaker +- getCalculatedValue() not working with some formulas involving error types - @MarkBaker +- evaluation of both return values in an IF() statement returning an error if either result was an error, irrespective of the IF evaluation - @MarkBaker +- Power in formulas: new calculation engine no longer treats ^ as a bitwise XOR operator - @MarkBaker +- Bugfixes and improvements to many of the Excel functions in PHPExcel - @MarkBaker + - Added optional "places" parameter in the BIN2HEX(), BIN2OCT, DEC2BIN(), DEC2OCT(), DEC2HEX(), HEX2BIN(), HEX2OCT(), OCT2BIN() and OCT2HEX() Engineering Functions + - Trap for unbalanced matrix sizes in MDETERM() and MINVERSE() Mathematic and Trigonometric functions + - Fix for default characters parameter value for LEFT() and RIGHT() Text functions + - Fix for GCD() and LCB() Mathematical functions when the parameters include a zero (0) value + - Fix for BIN2OCT() Engineering Function for 2s complement values (which were returning hex values) + - Fix for BESSELK() and BESSELY() Engineering functions + - Fix for IMDIV() Engineering Function when result imaginary component is positive (wasn't setting the sign) + - Fix for ERF() Engineering Function when called with an upper limit value for the integration + - Fix to DATE() Date/Time Function for year value of 0 + - Set ISPMT() function as category FINANCIAL + - Fix for DOLLARDE() and DOLLARFR() Financial functions + - Fix to EFFECT() Financial function (treating $nominal_rate value as a variable name rather than a value) + - Fix to CRITBINOM() Statistical function (CurrentValue and EssentiallyZero treated as constants rather than variables) + - Note that an Error in the function logic can still lead to a permanent loop + - Fix to MOD() Mathematical function to work with floating point results + - Fix for QUOTIENT() Mathematical function + - Fix to HOUR(), MINUTE() and SECOND() Date/Time functions to return an error when passing in a floating point value of 1.0 or greater, or less than 0 + - LOG() Function now correctly returns base-10 log when called with only one parameter, rather than the natural log as the default base + - Modified text functions to handle multibyte character set (UTF-8). + +## [1.6.7] - 2009-04-22 + +### BREAKING CHANGE + +In previous versions of PHPExcel up to and including 1.6.6, +when a cell had a date-like number format code, it was possible to enter a date +directly using an integer PHP-time without converting to Excel date format. +Starting with PHPExcel 1.6.7 this is no longer supported. Refer to the developer +documentation for more information on entering dates into a cell. + +### General + +- Deprecate misspelled setStriketrough() and getStriketrough() methods - @MarkBaker [CodePlex #9416](https://phpexcel.codeplex.com/workitem/9416) + +### Features + +- Performance improvement when saving file - @MarkBaker [CodePlex #9526](https://phpexcel.codeplex.com/workitem/9526) +- Check that sheet title has maximum 31 characters - @MarkBaker [CodePlex #9598](https://phpexcel.codeplex.com/workitem/9598) +- True support for Excel built-in number format codes - @MB, ET [CodePlex #9631](https://phpexcel.codeplex.com/workitem/9631) +- Ability to read defect BIFF5 Excel file without CODEPAGE record - @Erik Tilt [CodePlex #9683](https://phpexcel.codeplex.com/workitem/9683) +- Auto-detect which reader to invoke - @MarkBaker [CodePlex #9701](https://phpexcel.codeplex.com/workitem/9701) +- Deprecate insertion of dates using PHP-time (Unix time) [request for removal of feature] - @Erik Tilt [CodePlex #9214](https://phpexcel.codeplex.com/workitem/9214) +- Support for entering time values like '9:45', '09:45' using AdvancedValueBinder - @Erik Tilt [CodePlex #9747](https://phpexcel.codeplex.com/workitem/9747) + +### Bugfixes + +- DataType dependent horizontal alignment in HTML and PDF writer - @Erik Tilt [CodePlex #9797](https://phpexcel.codeplex.com/workitem/9797) +- Cloning data validation object causes script to stop - @MarkBaker [CodePlex #9375](https://phpexcel.codeplex.com/workitem/9375) +- Simultaneous repeating rows and repeating columns not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #9400](https://phpexcel.codeplex.com/workitem/9400) +- Simultaneous repeating rows and repeating columns not working with PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #9399](https://phpexcel.codeplex.com/workitem/9399) +- Row outline level not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #9437](https://phpexcel.codeplex.com/workitem/9437) +- Occasional notices with PHPExcel_Reader_Excel5 when Excel file contains drawing elements - @Erik Tilt [CodePlex #9452](https://phpexcel.codeplex.com/workitem/9452) +- PHPExcel_Reader_Excel5 fails as a whole when workbook contains images other than JPEG/PNG - @Erik Tilt [CodePlex #9453](https://phpexcel.codeplex.com/workitem/9453) +- Excel5 writer checks for iconv but does not necessarily use it - @Erik Tilt [CodePlex #9444](https://phpexcel.codeplex.com/workitem/9444) +- Altering a style on copied worksheet alters also the original - @Erik Tilt [CodePlex #9463](https://phpexcel.codeplex.com/workitem/9463) +- Formulas are incorrectly updated when a sheet is renamed - @MarkBaker [CodePlex #9480](https://phpexcel.codeplex.com/workitem/9480) +- PHPExcel_Worksheet::extractSheetTitle not treating single quotes correctly - @MarkBaker [CodePlex #9513](https://phpexcel.codeplex.com/workitem/9513) +- PHP Warning raised in function array_key_exists - @MarkBaker [CodePlex #9477](https://phpexcel.codeplex.com/workitem/9477) +- getAlignWithMargins() gives wrong value when using PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #9599](https://phpexcel.codeplex.com/workitem/9599) +- getScaleWithDocument() gives wrong value when using PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #9600](https://phpexcel.codeplex.com/workitem/9600) +- PHPExcel_Reader_Excel2007 not reading the first user-defined number format - @MarkBaker [CodePlex #9630](https://phpexcel.codeplex.com/workitem/9630) +- Print area converted to uppercase after read with PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #9647](https://phpexcel.codeplex.com/workitem/9647) +- Incorrect reading of scope for named range using PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #9661](https://phpexcel.codeplex.com/workitem/9661) +- Error with pattern (getFillType) and rbg (getRGB) - @MarkBaker [CodePlex #9690](https://phpexcel.codeplex.com/workitem/9690) +- AdvancedValueBinder affected by system timezone setting when inserting date values - @Erik Tilt [CodePlex #9712](https://phpexcel.codeplex.com/workitem/9712) +- PHPExcel_Reader_Excel2007 not reading value of active sheet index - @Erik Tilt [CodePlex #9743](https://phpexcel.codeplex.com/workitem/9743) +- getARGB() sometimes returns SimpleXMLElement object instead of string with PHPExcel_Reader_Excel2007 - @Erik Tilt [CodePlex #9742](https://phpexcel.codeplex.com/workitem/9742) +- Negative image offset causes defects in 14excel5.xls and 20readexcel5.xlsx - @Erik Tilt [CodePlex #9731](https://phpexcel.codeplex.com/workitem/9731) +- HTML & PDF Writer not working with mergeCells (regression since 1.6.5) - @Erik Tilt [CodePlex #9758](https://phpexcel.codeplex.com/workitem/9758) +- Too wide columns with HTML and PDF writer - @Erik Tilt [CodePlex #9774](https://phpexcel.codeplex.com/workitem/9774) +- PDF and cyrillic fonts - @MarkBaker [CodePlex #9775](https://phpexcel.codeplex.com/workitem/9775) +- Percentages not working correctly with HTML and PDF writers (shows 0.25% instead of 25%) - @Erik Tilt [CodePlex #9793](https://phpexcel.codeplex.com/workitem/9793) +- PHPExcel_Writer_HTML creates extra borders around cell contents using setUseInlineCss(true) - @Erik Tilt [CodePlex #9791](https://phpexcel.codeplex.com/workitem/9791) +- Problem with text wrap + merged cells in HTML and PDF writer - @Erik Tilt [CodePlex #9784](https://phpexcel.codeplex.com/workitem/9784) +- Adjacent path separators in include_path causing IOFactory to violate open_basedir restriction - @Erik Tilt [CodePlex #9814](https://phpexcel.codeplex.com/workitem/9814) + +## [1.6.6] - 2009-03-02 + +### General + +- Improve support for built-in number formats in PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #9102](https://phpexcel.codeplex.com/workitem/9102) +- Source files are in both UNIX and DOS formats - changed to UNIX - @Erik Tilt [CodePlex #9281](https://phpexcel.codeplex.com/workitem/9281) + +### Features + +- Update documentation: Which language to write formulas in? - @MarkBaker [CodePlex #9338](https://phpexcel.codeplex.com/workitem/9338) +- Ignore DEFCOLWIDTH records with value 8 in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8817](https://phpexcel.codeplex.com/workitem/8817) +- Support for width, height, offsetX, offsetY for images in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8847](https://phpexcel.codeplex.com/workitem/8847) +- Disk Caching in specific folder - @MarkBaker [CodePlex #8870](https://phpexcel.codeplex.com/workitem/8870) +- Added SUMX2MY2, SUMX2PY2, SUMXMY2, MDETERM and MINVERSE Mathematical and Trigonometric Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added CONVERT Engineering Function - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added DB, DDB, DISC, DOLLARDE, DOLLARFR, INTRATE, IPMT, PPMT, PRICEDISC, PRICEMAT and RECEIVED Financial Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added ACCRINTM, CUMIPMT, CUMPRINC, TBILLEQ, TBILLPRICE, TBILLYIELD, YIELDDISC and YIELDMAT Financial Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added DOLLAR Text Function - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added CORREL, COVAR, FORECAST, INTERCEPT, RSQ, SLOPE and STEYX Statistical Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added PEARSON Statistical Functions as a synonym for CORREL - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added LINEST, LOGEST (currently only valid for stats = false), TREND and GROWTH Statistical Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added RANK and PERCENTRANK Statistical Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Added ROMAN Mathematical Function (Classic form only) - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Update documentation to show example of getCellByColumnAndRow($col, $row) - @MarkBaker [CodePlex #8931](https://phpexcel.codeplex.com/workitem/8931) +- Implement worksheet, row and cell iterators - @MarkBaker [CodePlex #8770](https://phpexcel.codeplex.com/workitem/8770) +- Support for arbitrary defined names (named range) - @MarkBaker [CodePlex #9001](https://phpexcel.codeplex.com/workitem/9001) +- Update formulas when sheet title / named range title changes - @MB, ET [CodePlex #9016](https://phpexcel.codeplex.com/workitem/9016) +- Ability to read cached calculated value - @MarkBaker [CodePlex #9103](https://phpexcel.codeplex.com/workitem/9103) +- Support for Excel 1904 calendar date mode (Mac) - @MBaker, ET [CodePlex #8483](https://phpexcel.codeplex.com/workitem/8483) +- PHPExcel_Writer_Excel5 improvements writing shared strings table - @Erik Tilt [CodePlex #9194](https://phpexcel.codeplex.com/workitem/9194) +- PHPExcel_Writer_Excel5 iconv fallback when mbstring extension is not enabled - @Erik Tilt [CodePlex #9248](https://phpexcel.codeplex.com/workitem/9248) +- UTF-8 support in font names in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #9253](https://phpexcel.codeplex.com/workitem/9253) +- Implement value binding architecture - @MarkBaker [CodePlex #9215](https://phpexcel.codeplex.com/workitem/9215) +- PDF writer not working with UTF-8 - @MarkBaker [CodePlex #6742](https://phpexcel.codeplex.com/workitem/6742) + +### Bugfixes + +- Eliminate duplicate style entries in multisheet workbook written by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #9355](https://phpexcel.codeplex.com/workitem/9355) +- Redirect to client browser fails due to trailing white space in class definitions - @Erik Tilt [CodePlex #8810](https://phpexcel.codeplex.com/workitem/8810) +- Spurious column dimension element introduced in blank worksheet after using PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #8816](https://phpexcel.codeplex.com/workitem/8816) +- Image gets slightly narrower than expected when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8830](https://phpexcel.codeplex.com/workitem/8830) +- Image laid over non-visible row gets squeezed in height when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8831](https://phpexcel.codeplex.com/workitem/8831) +- PHPExcel_Reader_Excel5 fails when there are 10 or more images in the workbook - @Erik Tilt [CodePlex #8860](https://phpexcel.codeplex.com/workitem/8860) +- Different header/footer images in different sheets not working with PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #8909](https://phpexcel.codeplex.com/workitem/8909) +- Fractional seconds disappear when using PHPExcel_Reader_Excel2007 and PHPExcel_Reader_Excel5 - @MB, ET [CodePlex #8924](https://phpexcel.codeplex.com/workitem/8924) +- Images not showing in OpenOffice when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7994](https://phpexcel.codeplex.com/workitem/7994) +- Images not showing on print using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #9047](https://phpexcel.codeplex.com/workitem/9047) +- PHPExcel_Writer_Excel5 maximum allowed record size 4 bytes too short - @Erik Tilt [CodePlex #9085](https://phpexcel.codeplex.com/workitem/9085) +- Not numeric strings are formatted as dates and numbers using worksheet's toArray method - @MarkBaker [CodePlex #9119](https://phpexcel.codeplex.com/workitem/9119) +- Excel5 simple formula parsing error - @Erik Tilt [CodePlex #9132](https://phpexcel.codeplex.com/workitem/9132) +- Problems writing dates with CSV - @Erik Tilt [CodePlex #9206](https://phpexcel.codeplex.com/workitem/9206) +- PHPExcel_Reader_Excel5 reader fails with fatal error when reading group shapes - @Erik Tilt [CodePlex #9203](https://phpexcel.codeplex.com/workitem/9203) +- PHPExcel_Writer_Excel5 fails completely when workbook contains more than 57 colors - @Erik Tilt [CodePlex #9231](https://phpexcel.codeplex.com/workitem/9231) +- PHPExcel_Writer_PDF not compatible with autoload - @Erik Tilt [CodePlex #9244](https://phpexcel.codeplex.com/workitem/9244) +- Fatal error: Call to a member function getNestingLevel() on a non-object in PHPExcel/Reader/Excel5.php on line 690 - @Erik Tilt [CodePlex #9250](https://phpexcel.codeplex.com/workitem/9250) +- Notices when running test 04printing.php on PHP 5.2.8 - @MarkBaker [CodePlex #9246](https://phpexcel.codeplex.com/workitem/9246) +- insertColumn() spawns creation of spurious RowDimension - @MarkBaker [CodePlex #9294](https://phpexcel.codeplex.com/workitem/9294) +- Fix declarations for methods in extended Trend classes - @MarkBaker [CodePlex #9296](https://phpexcel.codeplex.com/workitem/9296) +- Fix to parameters for the FORECAST Statistical Function - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- PDF writer problems with cell height and text wrapping - @MarkBaker [CodePlex #7083](https://phpexcel.codeplex.com/workitem/7083) +- Fix test for calculated value in case the returned result is an array - @MarkBaker +- Column greater than 256 results in corrupt Excel file using PHPExcel_Writer_Excel5 - @Erik Tilt +- Excel Numberformat 0.00 results in non internal decimal places values in toArray() Method - @MarkBaker [CodePlex #9351](https://phpexcel.codeplex.com/workitem/9351) +- setAutoSize not taking into account text rotation - @MB,ET [CodePlex #9356](https://phpexcel.codeplex.com/workitem/9356) +- Call to undefined method PHPExcel_Worksheet_MemoryDrawing::getPath() in PHPExcel/Writer/HTML.php - @Erik Tilt [CodePlex #9372](https://phpexcel.codeplex.com/workitem/9372) + +## [1.6.5] - 2009-01-05 + +### General + +- Applied patch 2063 - @MarkBaker +- Optimise Shared Strings - @MarkBaker +- Optimise Cell Sorting - @MarkBaker +- Optimise Style Hashing - @MarkBaker +- UTF-8 enhancements - @Erik Tilt +- PHPExcel_Writer_HTML validation errors against strict HTML 4.01 / CSS 2.1 - @Erik Tilt +- Documented work items 6203 and 8110 in manual - @MarkBaker +- Restructure package hierachy so classes can be found more easily in auto-generated API (from work item 8468) - @Erik Tilt + +### Features + +- Redirect output to a client's browser: Update recommendation in documentation - @MarkBaker [CodePlex #8806](https://phpexcel.codeplex.com/workitem/8806) +- PHPExcel_Reader_Excel5 support for print gridlines - @Erik Tilt [CodePlex #7897](https://phpexcel.codeplex.com/workitem/7897) +- Screen gridlines support in Excel5 reader/writer - @Erik Tilt [CodePlex #7899](https://phpexcel.codeplex.com/workitem/7899) +- Option for adding image to spreadsheet from image resource in memory - @MB, ET [CodePlex #7552](https://phpexcel.codeplex.com/workitem/7552) +- PHPExcel_Reader_Excel5 style support for BIFF5 files (Excel 5.0 - Excel 95) - @Erik Tilt [CodePlex #7862](https://phpexcel.codeplex.com/workitem/7862) +- PHPExcel_Reader_Excel5 support for user-defined colors and special built-in colors - @Erik Tilt [CodePlex #7918](https://phpexcel.codeplex.com/workitem/7918) +- Support for freeze panes in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7992](https://phpexcel.codeplex.com/workitem/7992) +- Support for header and footer margins in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7996](https://phpexcel.codeplex.com/workitem/7996) +- Support for active sheet index in Excel5 reader/writer - @Erik Tilt [CodePlex #7997](https://phpexcel.codeplex.com/workitem/7997) +- Freeze panes not read by PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #7991](https://phpexcel.codeplex.com/workitem/7991) +- Support for screen zoom level (feature request) - @MB, ET [CodePlex #7993](https://phpexcel.codeplex.com/workitem/7993) +- Support for default style in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8012](https://phpexcel.codeplex.com/workitem/8012) +- Apple iWork / Numbers.app incompatibility - @MarkBaker [CodePlex #8094](https://phpexcel.codeplex.com/workitem/8094) +- Support "between rule" in conditional formatting - @MarkBaker [CodePlex #7931](https://phpexcel.codeplex.com/workitem/7931) +- Comment size, width and height control (feature request) - @MarkBaker [CodePlex #8308](https://phpexcel.codeplex.com/workitem/8308) +- Improve method for storing MERGEDCELLS records in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8418](https://phpexcel.codeplex.com/workitem/8418) +- Support for protectCells() in Excel5 reader/writer - @Erik Tilt [CodePlex #8435](https://phpexcel.codeplex.com/workitem/8435) +- Support for fitToWidth and fitToHeight pagesetup properties in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8472](https://phpexcel.codeplex.com/workitem/8472) +- Support for setShowSummaryBelow() and setShowSummaryRight() in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8489](https://phpexcel.codeplex.com/workitem/8489) +- Support for Excel 1904 calendar date mode (Mac) - @MarkBaker [CodePlex #8483](https://phpexcel.codeplex.com/workitem/8483) +- Excel5 reader: Support for reading images (bitmaps) - @Erik Tilt [CodePlex #7538](https://phpexcel.codeplex.com/workitem/7538) +- Support for default style in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8787](https://phpexcel.codeplex.com/workitem/8787) +- Modified calculate() method to return either an array or the first value from the array for those functions that return arrays rather than single values (e.g the MMULT and TRANSPOSE function). This performance can be modified based on the $returnArrayAsType which can be set/retrieved by calling the setArrayReturnType() and getArrayReturnType() methods of the PHPExcel_Calculation class. - @MarkBaker + +### Bugfixes + +- Added ERROR.TYPE Information Function, MMULT Mathematical and Trigonometry Function, and TRANSPOSE Lookup and Reference Function - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- setPrintGridlines(true) not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7896](https://phpexcel.codeplex.com/workitem/7896) +- Incorrect mapping of fill patterns in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7907](https://phpexcel.codeplex.com/workitem/7907) +- setShowGridlines(false) not working with PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #7898](https://phpexcel.codeplex.com/workitem/7898) +- getShowGridlines() gives inverted value when reading sheet with PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #7905](https://phpexcel.codeplex.com/workitem/7905) +- User-defined column width becomes slightly larger after read/write with Excel5 - @Erik Tilt [CodePlex #7944](https://phpexcel.codeplex.com/workitem/7944) +- Incomplete border style support in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7949](https://phpexcel.codeplex.com/workitem/7949) +- Conditional formatting "containsText" read/write results in MS Office Excel 2007 crash - @MarkBaker [CodePlex #7928](https://phpexcel.codeplex.com/workitem/7928) +- All sheets are always selected in output when using PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #7995](https://phpexcel.codeplex.com/workitem/7995) +- COLUMN function warning message during plain read/write - @MarkBaker [CodePlex #8013](https://phpexcel.codeplex.com/workitem/8013) +- setValue(0) results in string data type '0' - @MarkBaker [CodePlex #8155](https://phpexcel.codeplex.com/workitem/8155) +- Styles not removed when removing rows from sheet - @MarkBaker [CodePlex #8226](https://phpexcel.codeplex.com/workitem/8226) +- =IF formula causes fatal error during $objWriter->save() in Excel2007 format - @MarkBaker [CodePlex #8301](https://phpexcel.codeplex.com/workitem/8301) +- Exception thrown reading valid xls file: "Excel file is corrupt. Didn't find CONTINUE record while reading shared strings" - @Erik Tilt [CodePlex #8333](https://phpexcel.codeplex.com/workitem/8333) +- MS Outlook corrupts files generated by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8320](https://phpexcel.codeplex.com/workitem/8320) +- Undefined method PHPExcel_Worksheet::setFreezePane() in ReferenceHelper.php on line 271 - @MarkBaker [CodePlex #8351](https://phpexcel.codeplex.com/workitem/8351) +- Ampersands (&), left and right angles (<, >) in Rich-Text strings leads to corrupt output using PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #8401](https://phpexcel.codeplex.com/workitem/8401) +- Print header and footer not supporting UTF-8 in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8408](https://phpexcel.codeplex.com/workitem/8408) +- Vertical page breaks not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8463](https://phpexcel.codeplex.com/workitem/8463) +- Missing support for accounting underline types in PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8476](https://phpexcel.codeplex.com/workitem/8476) +- Infinite loops when reading corrupt xls file using PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8482](https://phpexcel.codeplex.com/workitem/8482) +- Sheet protection password not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8566](https://phpexcel.codeplex.com/workitem/8566) +- PHPExcel_Style_NumberFormat::FORMAT_NUMBER ignored by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8596](https://phpexcel.codeplex.com/workitem/8596) +- PHPExcel_Reader_Excel5 fails a whole when workbook contains a chart - @Erik Tilt [CodePlex #8781](https://phpexcel.codeplex.com/workitem/8781) +- Occasional loss of column widths using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #8788](https://phpexcel.codeplex.com/workitem/8788) +- Notices while reading formulas with deleted sheet references using PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #8795](https://phpexcel.codeplex.com/workitem/8795) +- Default style not read by PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #8807](https://phpexcel.codeplex.com/workitem/8807) +- Blank rows occupy too much space in file generated by PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #9341](https://phpexcel.codeplex.com/workitem/9341) + +## [1.6.4] - 2008-10-27 + +### Features + +- RK record number error in MS developer documentation: 0x007E should be 0x027E - @Erik Tilt [CodePlex #7882](https://phpexcel.codeplex.com/workitem/7882) +- getHighestColumn() returning "@" for blank worksheet causes corrupt output - @MarkBaker [CodePlex #7878](https://phpexcel.codeplex.com/workitem/7878) +- Implement ROW and COLUMN Lookup/Reference Functions (when specified with a parameter) - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement initial work on OFFSET Lookup/Reference Function (returning address rather than value at address) - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Excel5 reader: Page margins - @Erik Tilt [CodePlex #7416](https://phpexcel.codeplex.com/workitem/7416) +- Excel5 reader: Header & Footer - @Erik Tilt [CodePlex #7417](https://phpexcel.codeplex.com/workitem/7417) +- Excel5 reader support for page setup (paper size etc.) - @Erik Tilt [CodePlex #7449](https://phpexcel.codeplex.com/workitem/7449) +- Improve speed and memory consumption of PHPExcel_Writer_CSV - @MarkBaker [CodePlex #7445](https://phpexcel.codeplex.com/workitem/7445) +- Better recognition of number format in HTML, CSV, and PDF writer - @MarkBaker [CodePlex #7432](https://phpexcel.codeplex.com/workitem/7432) +- Font support: Superscript and Subscript - @MarkBaker [CodePlex #7485](https://phpexcel.codeplex.com/workitem/7485) +- Excel5 reader font support: Super- and subscript - @Erik Tilt [CodePlex #7509](https://phpexcel.codeplex.com/workitem/7509) +- Excel5 reader style support: Text rotation and stacked text - @Erik Tilt [CodePlex #7521](https://phpexcel.codeplex.com/workitem/7521) +- Excel5 reader: Support for hyperlinks - @Erik Tilt [CodePlex #7530](https://phpexcel.codeplex.com/workitem/7530) +- Import sheet by request - @MB, ET [CodePlex #7557](https://phpexcel.codeplex.com/workitem/7557) +- PHPExcel_Reader_Excel5 support for page breaks - @Erik Tilt [CodePlex #7607](https://phpexcel.codeplex.com/workitem/7607) +- PHPExcel_Reader_Excel5 support for shrink-to-fit - @Erik Tilt [CodePlex #7622](https://phpexcel.codeplex.com/workitem/7622) +- Support for error types - @MB, ET [CodePlex #7675](https://phpexcel.codeplex.com/workitem/7675) +- Excel5 reader true formula support - @Erik Tilt [CodePlex #7388](https://phpexcel.codeplex.com/workitem/7388) +- Support for named ranges (defined names) in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7701](https://phpexcel.codeplex.com/workitem/7701) +- Support for repeating rows and repeating columns (print titles) in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7781](https://phpexcel.codeplex.com/workitem/7781) +- Support for print area in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7783](https://phpexcel.codeplex.com/workitem/7783) +- Excel5 reader and writer support for horizontal and vertical centering of page - @Erik Tilt [CodePlex #7795](https://phpexcel.codeplex.com/workitem/7795) +- Applied patch 1962 - @MarkBaker +- Excel5 reader and writer support for hidden cells (formulas) - @Erik Tilt [CodePlex #7866](https://phpexcel.codeplex.com/workitem/7866) +- Support for indentation in cells (feature request) - @MB, ET [CodePlex #7612](https://phpexcel.codeplex.com/workitem/7612) + +### Bugfixes + +- Option for reading only specified interval of rows in a sheet - @MB, ET [CodePlex #7828](https://phpexcel.codeplex.com/workitem/7828) +- PHPExcel_Calculation_Functions::DATETIMENOW() and PHPExcel_Calculation_Functions::DATENOW() to force UTC - @MarkBaker [CodePlex #7367](https://phpexcel.codeplex.com/workitem/7367) +- Modified PHPExcel_Shared_Date::FormattedPHPToExcel() and PHPExcel_Shared_Date::ExcelToPHP to force datatype for return values - @MarkBaker [CodePlex #7395](https://phpexcel.codeplex.com/workitem/7395) +- Excel5 reader not producing UTF-8 strings with BIFF5 files - @Erik Tilt [CodePlex #7450](https://phpexcel.codeplex.com/workitem/7450) +- Array constant in formula gives run-time notice with Excel2007 writer - @MarkBaker [CodePlex #7470](https://phpexcel.codeplex.com/workitem/7470) +- PHPExcel_Reader_Excel2007 setReadDataOnly(true) returns Rich-Text - @MarkBaker [CodePlex #7494](https://phpexcel.codeplex.com/workitem/7494) +- PHPExcel_Reader_Excel5 setReadDataOnly(true) returns Rich-Text - @Erik Tilt [CodePlex #7496](https://phpexcel.codeplex.com/workitem/7496) +- Characters before superscript or subscript losing style - @MarkBaker [CodePlex #7497](https://phpexcel.codeplex.com/workitem/7497) +- Subscript not working with HTML writer - @MarkBaker [CodePlex #7507](https://phpexcel.codeplex.com/workitem/7507) +- DefaultColumnDimension not working on first column (A) - @MarkBaker [CodePlex #7508](https://phpexcel.codeplex.com/workitem/7508) +- Negative numbers are stored as text in PHPExcel_Writer_2007 - @MarkBaker [CodePlex #7527](https://phpexcel.codeplex.com/workitem/7527) +- Text rotation and stacked text not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7531](https://phpexcel.codeplex.com/workitem/7531) +- PHPExcel_Shared_Date::isDateTimeFormatCode erroneously says true - @MarkBaker [CodePlex #7536](https://phpexcel.codeplex.com/workitem/7536) +- Different images with same filename in separate directories become duplicates - @MarkBaker [CodePlex #7559](https://phpexcel.codeplex.com/workitem/7559) +- PHPExcel_Reader_Excel5 not returning sheet names as UTF-8 using for Excel 95 files - @Erik Tilt [CodePlex #7568](https://phpexcel.codeplex.com/workitem/7568) +- setAutoSize(true) on empty column gives column width of 10 using PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #7575](https://phpexcel.codeplex.com/workitem/7575) +- setAutoSize(true) on empty column gives column width of 255 using PHPExcel_Writer_Excel5 - @MB, ET [CodePlex #7573](https://phpexcel.codeplex.com/workitem/7573) +- Worksheet_Drawing bug - @MarkBaker [CodePlex #7514](https://phpexcel.codeplex.com/workitem/7514) +- getCalculatedValue() with REPT function causes script to stop - @MarkBaker [CodePlex #7593](https://phpexcel.codeplex.com/workitem/7593) +- getCalculatedValue() with LEN function causes script to stop - @MarkBaker [CodePlex #7594](https://phpexcel.codeplex.com/workitem/7594) +- Explicit fit-to-width (page setup) results in fit-to-height becoming 1 - @MarkBaker [CodePlex #7600](https://phpexcel.codeplex.com/workitem/7600) +- Fit-to-width value of 1 is lost after read/write of Excel2007 spreadsheet - @MarkBaker [CodePlex #7610](https://phpexcel.codeplex.com/workitem/7610) +- Conditional styles not read properly using PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #7516](https://phpexcel.codeplex.com/workitem/7516) +- PHPExcel_Writer_2007: Default worksheet style works only for first sheet - @MarkBaker [CodePlex #7611](https://phpexcel.codeplex.com/workitem/7611) +- Cannot Lock Cells using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #6940](https://phpexcel.codeplex.com/workitem/6940) +- Incorrect cell protection values found when using Excel5 reader - @Erik Tilt [CodePlex #7621](https://phpexcel.codeplex.com/workitem/7621) +- Default row height not working above highest row using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7623](https://phpexcel.codeplex.com/workitem/7623) +- Default column width does not get applied when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7637](https://phpexcel.codeplex.com/workitem/7637) +- Broken support for UTF-8 string formula results in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7642](https://phpexcel.codeplex.com/workitem/7642) +- UTF-8 sheet names not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7643](https://phpexcel.codeplex.com/workitem/7643) +- getCalculatedValue() with ISNONTEXT function causes script to stop - @MarkBaker [CodePlex #7631](https://phpexcel.codeplex.com/workitem/7631) +- Missing BIFF3 functions in PHPExcel_Writer_Excel5: USDOLLAR (YEN), FINDB, SEARCHB, REPLACEB, LEFTB, RIGHTB, MIDB, LENB, ASC, DBCS (JIS) - @Erik Tilt [CodePlex #7652](https://phpexcel.codeplex.com/workitem/7652) +- Excel5 reader doesn't read numbers correctly in 64-bit systems - @Erik Tilt [CodePlex #7663](https://phpexcel.codeplex.com/workitem/7663) +- Missing BIFF5 functions in PHPExcel_Writer_Excel5: ISPMT, DATEDIF, DATESTRING, NUMBERSTRING - @Erik Tilt [CodePlex #7667](https://phpexcel.codeplex.com/workitem/7667) +- Missing BIFF8 functions in PHPExcel_Writer_Excel5: GETPIVOTDATA, HYPERLINK, PHONETIC, AVERAGEA, MAXA, MINA, STDEVPA, VARPA, STDEVA, VARA - @Erik Tilt [CodePlex #7668](https://phpexcel.codeplex.com/workitem/7668) +- Wrong host value in PHPExcel_Shared_ZipStreamWrapper::stream_open() - @MarkBaker [CodePlex #7657](https://phpexcel.codeplex.com/workitem/7657) +- PHPExcel_Reader_Excel5 not reading explicitly entered error types in cells - @Erik Tilt [CodePlex #7676](https://phpexcel.codeplex.com/workitem/7676) +- Boolean and error data types not preserved for formula results in PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7678](https://phpexcel.codeplex.com/workitem/7678) +- PHPExcel_Reader_Excel2007 ignores cell data type - @MarkBaker [CodePlex #7695](https://phpexcel.codeplex.com/workitem/7695) +- PHPExcel_Reader_Excel5 ignores cell data type - @Erik Tilt [CodePlex #7712](https://phpexcel.codeplex.com/workitem/7712) +- PHPExcel_Writer_Excel5 not aware of data type - @Erik Tilt [CodePlex #7587](https://phpexcel.codeplex.com/workitem/7587) +- Long strings sometimes truncated when using PHPExcel_Reader_Excel5 - @Erik Tilt [CodePlex #7713](https://phpexcel.codeplex.com/workitem/7713) +- Direct entry of boolean or error type in cell not supported by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7727](https://phpexcel.codeplex.com/workitem/7727) +- PHPExcel_Reader_Excel2007: Error reading cell with data type string, date number format, and numeric-like cell value - @MarkBaker [CodePlex #7714](https://phpexcel.codeplex.com/workitem/7714) +- Row and column outlines (group indent level) not showing after using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7735](https://phpexcel.codeplex.com/workitem/7735) +- Missing UTF-8 support in number format codes for PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7737](https://phpexcel.codeplex.com/workitem/7737) +- Missing UTF-8 support with PHPExcel_Writer_Excel5 for explicit string in formula - @Erik Tilt [CodePlex #7750](https://phpexcel.codeplex.com/workitem/7750) +- Problem with class constants in PHPExcel_Style_NumberFormat - @MarkBaker [CodePlex #7726](https://phpexcel.codeplex.com/workitem/7726) +- Sometimes errors with PHPExcel_Reader_Excel5 reading hyperlinks - @Erik Tilt [CodePlex #7758](https://phpexcel.codeplex.com/workitem/7758) +- Hyperlink in cell always results in string data type when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7759](https://phpexcel.codeplex.com/workitem/7759) +- Excel file with blank sheet seen as broken in MS Office Excel 2007 when created by PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7771](https://phpexcel.codeplex.com/workitem/7771) +- PHPExcel_Reader_Excel5: Incorrect reading of formula with explicit string containing (escaped) double-quote - @Erik Tilt [CodePlex #7785](https://phpexcel.codeplex.com/workitem/7785) +- getCalculatedValue() fails on formula with sheet name containing (escaped) single-quote - @MarkBaker [CodePlex #7787](https://phpexcel.codeplex.com/workitem/7787) +- getCalculatedValue() fails on formula with explicit string containing (escaped) double-quote - @MarkBaker [CodePlex #7786](https://phpexcel.codeplex.com/workitem/7786) +- Problems with simultaneous repeatRowsAtTop and repeatColumnsAtLeft using Excel2007 reader and writer - @MarkBaker [CodePlex #7780](https://phpexcel.codeplex.com/workitem/7780) +- PHPExcel_Reader_Excel5: Error reading formulas with sheet reference containing special characters - @Erik Tilt [CodePlex #7802](https://phpexcel.codeplex.com/workitem/7802) +- Off-sheet references sheet!A1 not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7831](https://phpexcel.codeplex.com/workitem/7831) +- Repeating rows/columns (print titles), print area not working with PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7834](https://phpexcel.codeplex.com/workitem/7834) +- Formula having datetime number format shows as text when using PHPExcel_Writer_Excel5 - @Erik Tilt [CodePlex #7849](https://phpexcel.codeplex.com/workitem/7849) +- Cannot set formula to hidden using applyFromArray() - @MarkBaker [CodePlex #7863](https://phpexcel.codeplex.com/workitem/7863) +- HTML/PDF Writers limited to 26 columns by calculateWorksheetDimension (erroneous comparison in getHighestColumn() method) - @MarkBaker [CodePlex #7805](https://phpexcel.codeplex.com/workitem/7805) +- Formula returning error type is lost when read by PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #7873](https://phpexcel.codeplex.com/workitem/7873) +- PHPExcel_Reader_Excel5: Cell style lost for last column in group of blank cells - @Erik Tilt [CodePlex #7883](https://phpexcel.codeplex.com/workitem/7883) +- Column width sometimes collapses to auto size using Excel2007 reader/writer - @MarkBaker [CodePlex #7886](https://phpexcel.codeplex.com/workitem/7886) +- Data Validation Formula = 0 crashes Excel - @MarkBaker [CodePlex #9343](https://phpexcel.codeplex.com/workitem/9343) + +## [1.6.3] - 2008-08-25 + +### General + +- Modified PHPExcel_Shared_Date::PHPToExcel() to force UTC - @MarkBaker [CodePlex #7367](https://phpexcel.codeplex.com/workitem/7367) +- Applied patch 1629 - @MarkBaker +- Applied patch 1644 - @MarkBaker +- Implement repeatRow and repeatColumn in Excel5 writer - @MarkBaker [CodePlex #6485](https://phpexcel.codeplex.com/workitem/6485) + +### Features + +- Remove scene3d filter in Excel2007 drawing - @MarkBaker [CodePlex #6838](https://phpexcel.codeplex.com/workitem/6838) +- Implement CHOOSE and INDEX Lookup/Reference Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement CLEAN Text Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement YEARFRAC Date/Time Functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement 2 options for print/show gridlines - @MarkBaker [CodePlex #6508](https://phpexcel.codeplex.com/workitem/6508) +- Add VLOOKUP function (contribution) - @MarkBaker [CodePlex #7270](https://phpexcel.codeplex.com/workitem/7270) +- Implemented: ShrinkToFit - @MarkBaker [CodePlex #7182](https://phpexcel.codeplex.com/workitem/7182) +- Row heights not updated correctly when inserting new rows - @MarkBaker [CodePlex #7218](https://phpexcel.codeplex.com/workitem/7218) +- Copy worksheets within the same workbook - @MarkBaker [CodePlex #7157](https://phpexcel.codeplex.com/workitem/7157) +- Excel5 reader style support: horizontal and vertical alignment plus text wrap - @Erik Tilt [CodePlex #7290](https://phpexcel.codeplex.com/workitem/7290) +- Excel5 reader support for merged cells - @Erik Tilt [CodePlex #7294](https://phpexcel.codeplex.com/workitem/7294) +- Excel5 reader: Sheet Protection - @Erik Tilt [CodePlex #7296](https://phpexcel.codeplex.com/workitem/7296) +- Excel5 reader: Password for sheet protection - @Erik Tilt [CodePlex #7297](https://phpexcel.codeplex.com/workitem/7297) +- Excel5 reader: Column width - @Erik Tilt [CodePlex #7299](https://phpexcel.codeplex.com/workitem/7299) +- Excel5 reader: Row height - @Erik Tilt [CodePlex #7301](https://phpexcel.codeplex.com/workitem/7301) +- Excel5 reader: Font support - @Erik Tilt [CodePlex #7304](https://phpexcel.codeplex.com/workitem/7304) +- Excel5 reader: support for locked cells - @Erik Tilt [CodePlex #7324](https://phpexcel.codeplex.com/workitem/7324) +- Excel5 reader style support: Fill (background colors and patterns) - @Erik Tilt [CodePlex #7330](https://phpexcel.codeplex.com/workitem/7330) +- Excel5 reader style support: Borders (style and color) - @Erik Tilt [CodePlex #7332](https://phpexcel.codeplex.com/workitem/7332) +- Excel5 reader: Rich-Text support - @Erik Tilt [CodePlex #7346](https://phpexcel.codeplex.com/workitem/7346) +- Read Excel built-in number formats with Excel 2007 reader - @MarkBaker [CodePlex #7313](https://phpexcel.codeplex.com/workitem/7313) +- Excel5 reader: Number format support - @Erik Tilt [CodePlex #7317](https://phpexcel.codeplex.com/workitem/7317) +- Creating a copy of PHPExcel object - @MarkBaker [CodePlex #7362](https://phpexcel.codeplex.com/workitem/7362) +- Excel5 reader: support for row / column outline (group) - @Erik Tilt [CodePlex #7373](https://phpexcel.codeplex.com/workitem/7373) +- Implement default row/column sizes - @MarkBaker [CodePlex #7380](https://phpexcel.codeplex.com/workitem/7380) +- Writer HTML - option to return styles and table separately - @MarkBaker [CodePlex #7364](https://phpexcel.codeplex.com/workitem/7364) + +### Bugfixes + +- Excel5 reader: Support for remaining built-in number formats - @Erik Tilt [CodePlex #7393](https://phpexcel.codeplex.com/workitem/7393) +- Fixed rounding in HOUR MINUTE and SECOND Time functions, and improved performance for these - @MarkBaker +- Fix to TRIM function - @MarkBaker +- Fixed range validation in TIME Functions.php - @MarkBaker +- EDATE and EOMONTH functions now return date values based on the returnDateType flag - @MarkBaker +- Write date values that are the result of a calculation function correctly as Excel serialized dates rather than PHP serialized date values - @MarkBaker +- Excel2007 reader not always reading boolean correctly - @MarkBaker [CodePlex #6690](https://phpexcel.codeplex.com/workitem/6690) +- Columns above IZ - @MarkBaker [CodePlex #6275](https://phpexcel.codeplex.com/workitem/6275) +- Other locale than English causes Excel2007 writer to produce broken xlsx - @MarkBaker [CodePlex #6853](https://phpexcel.codeplex.com/workitem/6853) +- Typo: Number_fromat in NumberFormat.php - @MarkBaker [CodePlex #7061](https://phpexcel.codeplex.com/workitem/7061) +- Bug in Worksheet_BaseDrawing setWidth() - @MarkBaker [CodePlex #6865](https://phpexcel.codeplex.com/workitem/6865) +- PDF writer collapses column width for merged cells - @MarkBaker [CodePlex #6891](https://phpexcel.codeplex.com/workitem/6891) +- Issues with drawings filenames - @MarkBaker [CodePlex #6867](https://phpexcel.codeplex.com/workitem/6867) +- fromArray() local variable isn't defined - @MarkBaker [CodePlex #7073](https://phpexcel.codeplex.com/workitem/7073) +- PHPExcel_Writer_Excel5->setTempDir() not passed to all classes involved in writing to a file - @MarkBaker [CodePlex #7276](https://phpexcel.codeplex.com/workitem/7276) +- Excel5 reader not handling UTF-8 properly - @MarkBaker [CodePlex #7277](https://phpexcel.codeplex.com/workitem/7277) +- If you write a 0 value in cell, cell shows as empty - @MarkBaker [CodePlex #7327](https://phpexcel.codeplex.com/workitem/7327) +- Excel2007 writer: Row height ignored for empty rows - @MarkBaker [CodePlex #7302](https://phpexcel.codeplex.com/workitem/7302) +- Excel2007 (comments related error) - @MarkBaker [CodePlex #7281](https://phpexcel.codeplex.com/workitem/7281) +- Column width in other locale - @MarkBaker [CodePlex #7345](https://phpexcel.codeplex.com/workitem/7345) +- Excel2007 reader not reading underlined Rich-Text - @MarkBaker [CodePlex #7347](https://phpexcel.codeplex.com/workitem/7347) +- Excel5 reader converting booleans to strings - @Erik Tilt [CodePlex #7357](https://phpexcel.codeplex.com/workitem/7357) +- Recursive Object Memory Leak - @MarkBaker [CodePlex #7365](https://phpexcel.codeplex.com/workitem/7365) +- Excel2007 writer ignoring row dimensions without cells - @MarkBaker [CodePlex #7372](https://phpexcel.codeplex.com/workitem/7372) +- Excel5 reader is converting formatted numbers / dates to strings - @Erik Tilt [CodePlex #7382](https://phpexcel.codeplex.com/workitem/7382) + +## [1.6.2] - 2008-06-23 + +### General + +- Document style array values - @MarkBaker [CodePlex #6088](https://phpexcel.codeplex.com/workitem/6088) +- Applied patch 1195 - @MarkBaker +- Redirecting output to a client’s web browser - http headers - @MarkBaker [CodePlex #6178](https://phpexcel.codeplex.com/workitem/6178) +- Improve worksheet garbage collection - @MarkBaker [CodePlex #6187](https://phpexcel.codeplex.com/workitem/6187) +- Functions that return date values can now be configured to return as Excel serialized date/time, PHP serialized date/time, or a PHP date/time object. - @MarkBaker +- Functions that explicitly accept dates as parameters now permit values as Excel serialized date/time, PHP serialized date/time, a valid date string, or a PHP date/time object. - @MarkBaker +- Implement ACOSH, ASINH and ATANH functions for those operating platforms/PHP versions that don't include these functions - @MarkBaker +- Implement ATAN2 logic reversing the arguments as per Excel - @MarkBaker +- Additional validation of parameters for COMBIN - @MarkBaker + +### Features + +- Fixed validation for CEILING and FLOOR when the value and significance parameters have different signs; and allowed default value of 1 or -1 for significance when in GNUMERIC compatibility mode - @MarkBaker +- Implement ADDRESS, ISLOGICAL, ISTEXT and ISNONTEXT functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement COMPLEX, IMAGINARY, IMREAL, IMARGUMENT, IMCONJUGATE, IMABS, IMSUB, IMDIV, IMSUM, IMPRODUCT, IMSQRT, IMEXP, IMLN, IMLOG10, IMLOG2, IMPOWER IMCOS and IMSIN Engineering functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Implement NETWORKDAYS and WORKDAY Date/Time functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) +- Make cell column AAA available - @MarkBaker [CodePlex #6100](https://phpexcel.codeplex.com/workitem/6100) +- Mark particular cell as selected when opening Excel - @MarkBaker [CodePlex #6095](https://phpexcel.codeplex.com/workitem/6095) +- Multiple sheets in PDF and HTML - @MarkBaker [CodePlex #6120](https://phpexcel.codeplex.com/workitem/6120) +- Implement PHPExcel_ReaderFactory and PHPExcel_WriterFactory - @MarkBaker [CodePlex #6227](https://phpexcel.codeplex.com/workitem/6227) +- Set image root of PHPExcel_Writer_HTML - @MarkBaker [CodePlex #6249](https://phpexcel.codeplex.com/workitem/6249) +- Enable/disable calculation cache - @MarkBaker [CodePlex #6264](https://phpexcel.codeplex.com/workitem/6264) +- PDF writer and multi-line text - @MarkBaker [CodePlex #6259](https://phpexcel.codeplex.com/workitem/6259) +- Feature request - setCacheExpirationTime() - @MarkBaker [CodePlex #6350](https://phpexcel.codeplex.com/workitem/6350) +- Implement late-binding mechanisms to reduce memory footprint - @JB [CodePlex #6370](https://phpexcel.codeplex.com/workitem/6370) +- Implement shared styles - @JB [CodePlex #6430](https://phpexcel.codeplex.com/workitem/6430) +- Copy sheet from external Workbook to active Workbook - @MarkBaker [CodePlex #6391](https://phpexcel.codeplex.com/workitem/6391) + +### Bugfixes + +- Functions in Conditional Formatting - @MarkBaker [CodePlex #6428](https://phpexcel.codeplex.com/workitem/6428) +- Default Style in Excel5 - @MarkBaker [CodePlex #6096](https://phpexcel.codeplex.com/workitem/6096) +- Numbers starting with '+' cause Excel 2007 errors - @MarkBaker [CodePlex #6150](https://phpexcel.codeplex.com/workitem/6150) +- ExcelWriter5 is not PHP5 compatible, using it with E_STRICT results in a bunch of errors (applied patches) - @MarkBaker [CodePlex #6092](https://phpexcel.codeplex.com/workitem/6092) +- Error Reader Excel2007 line 653 foreach ($relsDrawing->Relationship as $ele) - @MarkBaker [CodePlex #6179](https://phpexcel.codeplex.com/workitem/6179) +- Worksheet toArray() screws up DATE - @MarkBaker [CodePlex #6229](https://phpexcel.codeplex.com/workitem/6229) +- References to a Richtext cell in a formula - @MarkBaker [CodePlex #6253](https://phpexcel.codeplex.com/workitem/6253) +- insertNewColumnBefore Bug - @MarkBaker [CodePlex #6285](https://phpexcel.codeplex.com/workitem/6285) +- Error reading Excel2007 file with shapes - @MarkBaker [CodePlex #6319](https://phpexcel.codeplex.com/workitem/6319) +- Determine whether date values need conversion from PHP dates to Excel dates before writing to file, based on the data type (float or integer) - @MarkBaker [CodePlex #6302](https://phpexcel.codeplex.com/workitem/6302) +- Fixes to DATE function when it is given negative input parameters - @MarkBaker +- PHPExcel handles empty cells other than Excel - @MarkBaker [CodePlex #6347](https://phpexcel.codeplex.com/workitem/6347) +- PHPExcel handles 0 and "" as being the same - @MarkBaker [CodePlex #6348](https://phpexcel.codeplex.com/workitem/6348) +- Problem Using Excel2007 Reader for Spreadsheets containing images - @MarkBaker [CodePlex #6357](https://phpexcel.codeplex.com/workitem/6357) +- ShowGridLines ignored when reading/writing Excel 2007 - @MarkBaker [CodePlex #6359](https://phpexcel.codeplex.com/workitem/6359) +- Bug With Word Wrap in Excel 2007 Reader - @MarkBaker [CodePlex #6426](https://phpexcel.codeplex.com/workitem/6426) + +## [1.6.1] - 2008-04-28 + +### General + +- Fix documentation printing - @MarkBaker [CodePlex #5532](https://phpexcel.codeplex.com/workitem/5532) +- Memory usage improvements - @MarkBaker [CodePlex #5586](https://phpexcel.codeplex.com/workitem/5586) +- Applied patch 990 - @MarkBaker + +### Features + +- Applied patch 991 - @MarkBaker +- Implement PHPExcel_Reader_Excel5 - @BM [CodePlex #2841](https://phpexcel.codeplex.com/workitem/2841) +- Implement "toArray" and "fromArray" method - @MarkBaker [CodePlex #5564](https://phpexcel.codeplex.com/workitem/5564) +- Read shared formula - @MarkBaker [CodePlex #5665](https://phpexcel.codeplex.com/workitem/5665) +- Read image twoCellAnchor - @MarkBaker [CodePlex #5681](https://phpexcel.codeplex.com/workitem/5681) +- &G Image as bg for headerfooter - @MarkBaker [CodePlex #4446](https://phpexcel.codeplex.com/workitem/4446) +- Implement page layout functionality for Excel5 format - @MarkBaker [CodePlex #5834](https://phpexcel.codeplex.com/workitem/5834) + +### Bugfixes + +- Feature request: PHPExcel_Writer_PDF - @MarkBaker [CodePlex #6039](https://phpexcel.codeplex.com/workitem/6039) +- DefinedNames null check - @MarkBaker [CodePlex #5517](https://phpexcel.codeplex.com/workitem/5517) +- Hyperlinks should not always have trailing slash - @MarkBaker [CodePlex #5463](https://phpexcel.codeplex.com/workitem/5463) +- Saving Error - Uncaught exception (#REF! named range) - @MarkBaker [CodePlex #5592](https://phpexcel.codeplex.com/workitem/5592) +- Error when creating Zip file on Linux System (Not Windows) - @MarkBaker [CodePlex #5634](https://phpexcel.codeplex.com/workitem/5634) +- Time incorrecly formated - @MarkBaker [CodePlex #5876](https://phpexcel.codeplex.com/workitem/5876) +- Conditional formatting - second rule not applied - @MarkBaker [CodePlex #5914](https://phpexcel.codeplex.com/workitem/5914) +- PHPExcel_Reader_Excel2007 cannot load PHPExcel_Shared_File - @MarkBaker [CodePlex #5978](https://phpexcel.codeplex.com/workitem/5978) +- Output redirection to web browser - @MarkBaker [CodePlex #6020](https://phpexcel.codeplex.com/workitem/6020) + +## [1.6.0] - 2008-02-14 + +### Features + +- Use PHPExcel datatypes in formula calculation - @MarkBaker [CodePlex #3156](https://phpexcel.codeplex.com/workitem/3156) +- Center on page when printing - @MarkBaker [CodePlex #5019](https://phpexcel.codeplex.com/workitem/5019) +- Hyperlink to other spreadsheet - @MarkBaker [CodePlex #5099](https://phpexcel.codeplex.com/workitem/5099) +- Set the print area of a worksheet - @MarkBaker [CodePlex #5104](https://phpexcel.codeplex.com/workitem/5104) +- Read "definedNames" property of worksheet - @MarkBaker [CodePlex #5118](https://phpexcel.codeplex.com/workitem/5118) +- Set default style for all cells - @MarkBaker [CodePlex #5338](https://phpexcel.codeplex.com/workitem/5338) +- Named Ranges - @MarkBaker [CodePlex #4216](https://phpexcel.codeplex.com/workitem/4216) + +### Bugfixes + +- Implement worksheet references (Sheet1!A1) - @MarkBaker [CodePlex #5398](https://phpexcel.codeplex.com/workitem/5398) +- Redirect output to a client's web browser - @MarkBaker [CodePlex #4967](https://phpexcel.codeplex.com/workitem/4967) +- "File Error: data may have been lost." seen in Excel 2007 and Excel 2003 SP3 when opening XLS file - @MarkBaker [CodePlex #5008](https://phpexcel.codeplex.com/workitem/5008) +- Bug in style's getHashCode() - @MarkBaker [CodePlex #5165](https://phpexcel.codeplex.com/workitem/5165) +- PHPExcel_Reader not correctly reading numeric values - @MarkBaker [CodePlex #5165](https://phpexcel.codeplex.com/workitem/5165) +- Text rotation is read incorrectly - @MarkBaker [CodePlex #5324](https://phpexcel.codeplex.com/workitem/5324) +- Enclosure " and data " result a bad data : \" instead of "" - @MarkBaker [CodePlex #5326](https://phpexcel.codeplex.com/workitem/5326) +- Formula parser - IF statement returning array instead of scalar - @MarkBaker [CodePlex #5332](https://phpexcel.codeplex.com/workitem/5332) +- setFitToWidth(nbpage) & setFitToWidth(nbpage) work partially - @MarkBaker [CodePlex #5351](https://phpexcel.codeplex.com/workitem/5351) +- Worksheet::setTitle() causes unwanted renaming - @MarkBaker [CodePlex #5361](https://phpexcel.codeplex.com/workitem/5361) +- Hyperlinks not working. Results in broken xlsx file. - @MarkBaker [CodePlex #5407](https://phpexcel.codeplex.com/workitem/5407) + +## [1.5.5] - 2007-12-24 + +### General + +- Grouping Rows - @MarkBaker [CodePlex #4135](https://phpexcel.codeplex.com/workitem/4135) + +### Features + +- Semi-nightly builds - @MarkBaker [CodePlex #4427](https://phpexcel.codeplex.com/workitem/4427) +- Implement "date" datatype - @MarkBaker [CodePlex #3155](https://phpexcel.codeplex.com/workitem/3155) +- Date format not honored in CSV writer - @MarkBaker [CodePlex #4150](https://phpexcel.codeplex.com/workitem/4150) +- RichText and sharedStrings - @MarkBaker [CodePlex #4199](https://phpexcel.codeplex.com/workitem/4199) +- Implement more Excel calculation functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) + - Addition of DATE, DATEDIF, DATEVALUE, DAY, DAYS360- Implement more Excel calculation functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) + - Addition of AVEDEV, HARMEAN and GEOMEAN + - Addition of the BINOMDIST (Non-cumulative only), COUNTBLANK, EXPONDIST, FISHER, FISHERINV, NORMDIST, NORMSDIST, PERMUT, POISSON (Non-cumulative only) and STANDARDIZE Statistical Functions + - Addition of the CEILING, COMBIN, EVEN, FACT, FACTDOUBLE, FLOOR, MULTINOMIAL, ODD, ROUNDDOWN, ROUNDUP, SIGN, SQRTPI and SUMSQ Mathematical Functions + - Addition of the NORMINV, NORMSINV, CONFIDENCE and SKEW Statistical Functions + - Addition of the CRITBINOM, HYPGEOMDIST, KURT, LOGINV, LOGNORMDIST, NEGBINOMDIST and WEIBULL Statistical Functions + - Addition of the LARGE, PERCENTILE, QUARTILE, SMALL and TRIMMEAN Statistical Functions + - Addition of the BIN2HEX, BIN2OCT, DELTA, ERF, ERFC, GESTEP, HEX2BIN, HEX2DEC, HEX2OCT, OCT2BIN and OCT2HEX Engineering Functions + - Addition of the CHIDIST, GAMMADIST and GAMMALN Statistical Functions + - Addition of the GCD, LCM, MROUND and SUBTOTAL Mathematical Functions + - Addition of the LOWER, PROPER and UPPER Text Functions + - Addition of the BETADIST and BETAINV Statistical Functions + - Addition of the CHIINV and GAMMAINV Statistical Functions + - Addition of the SERIESSUM Mathematical Function + - Addition of the CHAR, CODE, FIND, LEN, REPT, SEARCH, T, TRIM Text Functions + - Addition of the FALSE and TRUE Boolean Functions + - Addition of the TDIST and TINV Statistical Functions + - Addition of the EDATE, EOMONTH, YEAR, MONTH, TIME, TIMEVALUE, HOUR, MINUTE, SECOND, WEEKDAY, WEEKNUM, NOW, TODAY and Date/Time Function + - Addition of the BESSELI, BESSELJ, BESSELK and BESSELY Engineering Functions + - Addition of the SLN and SYD Financial Functions + - reworked MODE calculation to handle floating point numbers + - Improved error trapping for invalid input values + - Fix to SMALL, LARGE, PERCENTILE and TRIMMEAN to eliminate non-numeric values + - Added CDF to BINOMDIST and POISSON + - Fix to a potential endless loop in CRITBINOM, together with other bugfixes to the algorithm + - Fix to SQRTPI so that it will work with a real value parameter rather than just integers + - Trap for passing negative values to FACT + - Improved accuracy of the NORMDIST cumulative function, and of the ERF and ERFC functions + - Replicated Excel data-type and error handling for BIN, DEC, OCT and HEX conversion functions + - Replicated Excel data-type and error handling for AND and OR Boolean functions + - Bugfix to MROUND + - Rework of the DATE, DATEVALUE, DAY, DAYS360 and DATEDIF date/Time functions to use Excel dates rather than straight PHP dates + - Rework of the AND, OR Boolean functions to ignore string values + - Rework of the BIN2DEC, BIN2HEX, BIN2OCT, DEC2BIN, DEC2HEX, DEC2OCT Engineering functions to handle two's complement + - Excel, Gnumeric and OpenOffice Calc compatibility flag for functions + - Note, not all functions have yet been written to work with the Gnumeric and OpenOffice Calc compatibility flags + - 1900 or 1904 Calendar flag for date functions + - Reworked ExcelToPHP date method to handle the Excel 1900 leap year + - Note that this will not correctly return values prior to 13-Dec-1901 20:45:52 as this is the minimum value that PHP date serial values can handle. If you need to work with dates prior to this, then an ExcelToPHPObject method has been added which will work correctly with values between Excel's 1900 calendar base date of 1-Jan-1900, and 13-Dec-1901 + - Addition of ExcelToPHPObject date method to return a PHP DateTime object from an Excel date serial value + - PHPToExcel method modified to accept either PHP date serial numbers or PHP DateTime objects + - Addition of FormattedPHPToExcel which will accept a date and time broken to into year, month, day, hour, minute, second and return an Excel date serial value- Control characters in Excel 2007 - @MarkBaker [CodePlex #4485](https://phpexcel.codeplex.com/workitem/4485) +- BaseDrawing::setWidthAndHeight method request - @MarkBaker [CodePlex #4796](https://phpexcel.codeplex.com/workitem/4796) +- Page Setup -> Print Titles -> Sheet -> 'Rows to repeat at top' - @MarkBaker [CodePlex #4798](https://phpexcel.codeplex.com/workitem/4798) + +### Bugfixes + +- Comment functionality - @MarkBaker [CodePlex #4433](https://phpexcel.codeplex.com/workitem/4433) +- Undefined variable in PHPExcel_Writer_Serialized - @MarkBaker [CodePlex #4124](https://phpexcel.codeplex.com/workitem/4124) +- Notice: Object of class PHPExcel_RichText could not be converted to int - @MarkBaker [CodePlex #4125](https://phpexcel.codeplex.com/workitem/4125) +- Excel5Writer: utf8 string not converted to utf16 - @MarkBaker [CodePlex #4126](https://phpexcel.codeplex.com/workitem/4126) +- PHPExcel_RichText and autosize - @MarkBaker [CodePlex #4180](https://phpexcel.codeplex.com/workitem/4180) +- Excel5Writer produces broken xls files after change mentioned in work item 4126 - @MarkBaker [CodePlex #4574](https://phpexcel.codeplex.com/workitem/4574) +- Small bug in PHPExcel_Reader_Excel2007 function _readStyle - @MarkBaker [CodePlex #4797](https://phpexcel.codeplex.com/workitem/4797) + +## [1.5.0] - 2007-10-23 + +### Features + +- Refactor PHPExcel Drawing - @MarkBaker [CodePlex #3265](https://phpexcel.codeplex.com/workitem/3265) +- Update Shared/OLE.php to latest version from PEAR - @CS [CodePlex #3079](https://phpexcel.codeplex.com/workitem/3079) +- Excel2007 vs Excel2003 compatibility pack - @MarkBaker [CodePlex #3217](https://phpexcel.codeplex.com/workitem/3217) +- Cell protection (lock/unlock) - @MarkBaker [CodePlex #3234](https://phpexcel.codeplex.com/workitem/3234) +- Create clickable links (hyperlinks) - @MarkBaker [CodePlex #3543](https://phpexcel.codeplex.com/workitem/3543) +- Additional page setup parameters - @MarkBaker [CodePlex #3241](https://phpexcel.codeplex.com/workitem/3241) +- Make temporary file path configurable (Excel5) - @MarkBaker [CodePlex #3300](https://phpexcel.codeplex.com/workitem/3300) +- Small addition to applyFromArray for font - @MarkBaker [CodePlex #3306](https://phpexcel.codeplex.com/workitem/3306) + +### Bugfixes + +- Better feedback when save of file is not possible - @MarkBaker [CodePlex #3373](https://phpexcel.codeplex.com/workitem/3373) +- Text Rotation - @MarkBaker [CodePlex #3181](https://phpexcel.codeplex.com/workitem/3181) +- Small bug in Page Orientation - @MarkBaker [CodePlex #3237](https://phpexcel.codeplex.com/workitem/3237) +- insertNewColumnBeforeByColumn undefined - @MarkBaker [CodePlex #3812](https://phpexcel.codeplex.com/workitem/3812) +- Sheet references not working in formula (Excel5 Writer) - @MarkBaker [CodePlex #3893](https://phpexcel.codeplex.com/workitem/3893) + +## [1.4.5] - 2007-08-23 + +### General + +- Class file endings - @MarkBaker [CodePlex #3003](https://phpexcel.codeplex.com/workitem/3003) +- Different calculation engine improvements - @MarkBaker [CodePlex #3081](https://phpexcel.codeplex.com/workitem/3081) +- Different improvements in PHPExcel_Reader_Excel2007 - @MarkBaker [CodePlex #3082](https://phpexcel.codeplex.com/workitem/3082) + +### Features + +- Set XML indentation in PHPExcel_Writer_Excel2007 - @MarkBaker [CodePlex #3146](https://phpexcel.codeplex.com/workitem/3146) +- Optionally store temporary Excel2007 writer data in file instead of memory - @MarkBaker [CodePlex #3159](https://phpexcel.codeplex.com/workitem/3159) +- Implement show/hide gridlines - @MarkBaker [CodePlex #3063](https://phpexcel.codeplex.com/workitem/3063) +- Implement option to read only data - @MarkBaker [CodePlex #3064](https://phpexcel.codeplex.com/workitem/3064) +- Optionally disable formula precalculation - @MarkBaker [CodePlex #3080](https://phpexcel.codeplex.com/workitem/3080) +- Explicitly set cell datatype - @MarkBaker [CodePlex #3154](https://phpexcel.codeplex.com/workitem/3154) + +### Bugfixes + +- Implement more Excel calculation functions - @MarkBaker [CodePlex #2346](https://phpexcel.codeplex.com/workitem/2346) + - Addition of MINA, MAXA, COUNTA, AVERAGEA, MEDIAN, MODE, DEVSQ, STDEV, STDEVA, STDEVP, STDEVPA, VAR, VARA, VARP and VARPA Excel Functions + - Fix to SUM, PRODUCT, QUOTIENT, MIN, MAX, COUNT and AVERAGE functions when cell contains a numeric value in a string datatype, bringing it in line with MS Excel behaviour- File_exists on ZIP fails on some installations - @MarkBaker [CodePlex #2881](https://phpexcel.codeplex.com/workitem/2881) +- Argument in textRotation should be -90..90 - @MarkBaker [CodePlex #2879](https://phpexcel.codeplex.com/workitem/2879) +- Excel2007 reader/writer not implementing OpenXML/SpreadsheetML styles 100% correct - @MarkBaker [CodePlex #2883](https://phpexcel.codeplex.com/workitem/2883) +- Active sheet index not read/saved - @MarkBaker [CodePlex #2513](https://phpexcel.codeplex.com/workitem/2513) +- Print and print preview of generated XLSX causes Excel2007 to crash - @MarkBaker [CodePlex #2935](https://phpexcel.codeplex.com/workitem/2935) +- Error in Calculations - COUNT() function - @MarkBaker [CodePlex #2952](https://phpexcel.codeplex.com/workitem/2952) +- HTML and CSV writer not writing last row - @MarkBaker [CodePlex #3002](https://phpexcel.codeplex.com/workitem/3002) +- Memory leak in Excel5 writer - @MarkBaker [CodePlex #3017](https://phpexcel.codeplex.com/workitem/3017) +- Printing (PHPExcel_Writer_Excel5) - @MarkBaker [CodePlex #3044](https://phpexcel.codeplex.com/workitem/3044) +- Problems reading zip:// - @MarkBaker [CodePlex #3046](https://phpexcel.codeplex.com/workitem/3046) +- Error reading conditional formatting - @MarkBaker [CodePlex #3047](https://phpexcel.codeplex.com/workitem/3047) +- Bug in Excel5 writer (storePanes) - @MarkBaker [CodePlex #3067](https://phpexcel.codeplex.com/workitem/3067) +- Memory leak in PHPExcel_Style_Color - @MarkBaker [CodePlex #3077](https://phpexcel.codeplex.com/workitem/3077) + +## [1.4.0] - 2007-07-23 + +### General + +- Coding convention / code cleanup - @MarkBaker [CodePlex #2687](https://phpexcel.codeplex.com/workitem/2687) +- Use set_include_path in tests - @MarkBaker [CodePlex #2717](https://phpexcel.codeplex.com/workitem/2717) + +### Features + +- Move PHPExcel_Writer_Excel5 OLE to PHPExcel_Shared_OLE - @MarkBaker [CodePlex #2812](https://phpexcel.codeplex.com/workitem/2812) +- Hide/Unhide Column or Row - @MarkBaker [CodePlex #2679](https://phpexcel.codeplex.com/workitem/2679) +- Implement multi-cell styling - @MarkBaker [CodePlex #2271](https://phpexcel.codeplex.com/workitem/2271) +- Implement CSV file format (reader/writer) - @MarkBaker [CodePlex #2720](https://phpexcel.codeplex.com/workitem/2720) + +### Bugfixes + +- Implement HTML file format - @MarkBaker [CodePlex #2845](https://phpexcel.codeplex.com/workitem/2845) +- Active sheet index not read/saved - @MarkBaker [CodePlex #2513](https://phpexcel.codeplex.com/workitem/2513) +- Freeze Panes with PHPExcel_Writer_Excel5 - @MarkBaker [CodePlex #2678](https://phpexcel.codeplex.com/workitem/2678) +- OLE.php - @MarkBaker [CodePlex #2680](https://phpexcel.codeplex.com/workitem/2680) +- Copy and pasting multiple drop-down list cells breaks reader - @MarkBaker [CodePlex #2736](https://phpexcel.codeplex.com/workitem/2736) +- Function setAutoFilterByColumnAndRow takes wrong arguments - @MarkBaker [CodePlex #2775](https://phpexcel.codeplex.com/workitem/2775) +- Simplexml_load_file fails on ZipArchive - @MarkBaker [CodePlex #2858](https://phpexcel.codeplex.com/workitem/2858) + +## [1.3.5] - 2007-06-27 + +### Features + +- Documentation - @MarkBaker [CodePlex #15](https://phpexcel.codeplex.com/workitem/15) +- PHPExcel_Writer_Excel5 - @JV +- PHPExcel_Reader_Excel2007: Image shadows - @JV +- Data validation - @MarkBaker [CodePlex #2385](https://phpexcel.codeplex.com/workitem/2385) + +### Bugfixes + +- Implement richtext strings - @MarkBaker +- Empty relations when adding image to any sheet but the first one - @MarkBaker [CodePlex #2443](https://phpexcel.codeplex.com/workitem/2443) +- Excel2007 crashes on print preview - @MarkBaker [CodePlex #2536](https://phpexcel.codeplex.com/workitem/2536) + +## [1.3.0] - 2007-06-05 + +### General + +- Create PEAR package - @MarkBaker [CodePlex #1942](https://phpexcel.codeplex.com/workitem/1942) + +### Features + +- Replace *->duplicate() by __clone() - @MarkBaker [CodePlex #2331](https://phpexcel.codeplex.com/workitem/2331) +- PHPExcel_Reader_Excel2007: Column auto-size, Protection, Merged cells, Wrap text, Page breaks, Auto filter, Images - @JV +- Implement "freezing" panes - @MarkBaker [CodePlex #245](https://phpexcel.codeplex.com/workitem/245) +- Cell addressing alternative - @MarkBaker [CodePlex #2273](https://phpexcel.codeplex.com/workitem/2273) +- Implement cell word-wrap attribute - @MarkBaker [CodePlex #2270](https://phpexcel.codeplex.com/workitem/2270) +- Auto-size column - @MarkBaker [CodePlex #2282](https://phpexcel.codeplex.com/workitem/2282) +- Implement formula calculation - @MarkBaker [CodePlex #241](https://phpexcel.codeplex.com/workitem/241) + +### Bugfixes + +- Insert/remove row/column - @MarkBaker [CodePlex #2375](https://phpexcel.codeplex.com/workitem/2375) +- PHPExcel_Worksheet::getCell() should not accept absolute coordinates - @MarkBaker [CodePlex #1931](https://phpexcel.codeplex.com/workitem/1931) +- Cell reference without row number - @MarkBaker [CodePlex #2272](https://phpexcel.codeplex.com/workitem/2272) +- Styles with same coordinate but different worksheet - @MarkBaker [CodePlex #2276](https://phpexcel.codeplex.com/workitem/2276) +- PHPExcel_Worksheet->getCellCollection() usort error - @MarkBaker [CodePlex #2290](https://phpexcel.codeplex.com/workitem/2290) +- Bug in PHPExcel_Cell::stringFromColumnIndex - @SS [CodePlex #2353](https://phpexcel.codeplex.com/workitem/2353) +- Reader: numFmts can be missing, use cellStyleXfs instead of cellXfs in styles - @JV [CodePlex #2353](https://phpexcel.codeplex.com/workitem/2353) + +## [1.2.0] - 2007-04-26 + +### General + +- Stringtable attribute "count" not necessary, provides wrong info to Excel sometimes... - @MarkBaker +- Updated tests to address more document properties - @MarkBaker +- Some refactoring in PHPExcel_Writer_Excel2007_Workbook - @MarkBaker +- New package: PHPExcel_Shared - @MarkBaker +- Password hashing algorithm implemented in PHPExcel_Shared_PasswordHasher - @MarkBaker +- Moved pixel conversion functions to PHPExcel_Shared_Drawing - @MarkBaker +- Switch over to LGPL license - @MarkBaker [CodePlex #244](https://phpexcel.codeplex.com/workitem/244) + +### Features + +- Include PHPExcel version in file headers - @MarkBaker [CodePlex #5](https://phpexcel.codeplex.com/workitem/5) +- Autofilter - @MarkBaker [CodePlex #6](https://phpexcel.codeplex.com/workitem/6) +- Extra document property: keywords - @MarkBaker [CodePlex #7](https://phpexcel.codeplex.com/workitem/7) +- Extra document property: category - @MarkBaker [CodePlex #8](https://phpexcel.codeplex.com/workitem/8) +- Document security - @MarkBaker [CodePlex #9](https://phpexcel.codeplex.com/workitem/9) +- PHPExcel_Writer_Serialized and PHPExcel_Reader_Serialized - @MarkBaker [CodePlex #10](https://phpexcel.codeplex.com/workitem/10) +- Alternative syntax: Addressing a cell - @MarkBaker [CodePlex #11](https://phpexcel.codeplex.com/workitem/11) +- Merge cells - @MarkBaker [CodePlex #12](https://phpexcel.codeplex.com/workitem/12) + +### Bugfixes + +- Protect ranges of cells with a password - @MarkBaker [CodePlex #13](https://phpexcel.codeplex.com/workitem/13) +- (style/fill/patternFill/fgColor or bgColor can be empty) - @JV [CodePlex #14](https://phpexcel.codeplex.com/workitem/14) + +## [1.1.1] - 2007-03-26 + +### General + +- Syntax error in "Classes/PHPExcel/Writer/Excel2007.php" on line 243 - @MarkBaker [CodePlex #1250](https://phpexcel.codeplex.com/workitem/1250) +- Reader should check if file exists and throws an exception when it doesn't - @MarkBaker [CodePlex #1282](https://phpexcel.codeplex.com/workitem/1282) + +## [1.1.0] - 2007-03-22 + +### Bugfixes + +- Style information lost after passing trough Excel2007_Reader - @MarkBaker [CodePlex #836](https://phpexcel.codeplex.com/workitem/836) + +### General + +- Number of columns > AZ fails fixed in PHPExcel_Cell::columnIndexFromString - @MarkBaker [CodePlex #913](https://phpexcel.codeplex.com/workitem/913) + +### Features + +- Added a brief file with installation instructions - @MarkBaker +- Page breaks (horizontal and vertical) - @MarkBaker +- Image shadows - @MarkBaker + +## [1.0.0] - 2007-02-22 + +### Bugfixes + +- PHPExcel->removeSheetByIndex now re-orders sheets after deletion, so no array indexes are lost - @JV +- PHPExcel_Writer_Excel2007_Worksheet::_writeCols() used direct assignment to $pSheet->getColumnDimension('A')->Width instead of $pSheet->getColumnDimension('A')->setWidth() - @JV +- DocumentProperties used $this->LastModifiedBy instead of $this->_lastModifiedBy. - @JV + +### General + +- Only first = should be removed when writing formula in PHPExcel_Writer_Excel2007_Worksheet. - @JV +- Consistency of method names to camelCase - @JV +- Updated tests to match consistency changes - @JV +- Detection of mime-types now with image_type_to_mime_type() - @JV +- Constants now hold string value used in Excel 2007 - @JV + +### Features + +- Fixed folder name case (WorkSheet -> Worksheet) - @MarkBaker +- PHPExcel classes (not the Writer classes) can be duplicated, using a duplicate() method. - @MarkBaker +- Cell styles can now be duplicated to a range of cells using PHPExcel_Worksheet->duplicateStyle() - @MarkBaker +- Conditional formatting - @MarkBaker +- Reader for Excel 2007 (not supporting full specification yet!) - @JV + +## [1.0.0 RC] - 2007-01-31 + +- Project name has been changed to PHPExcel +- Project homepage is now http://www.codeplex.com/PHPExcel +- Started versioning at number: PHPExcel 1.0.0 RC + +## 2007-01-22 + +- Fixed some performance issues on large-scale worksheets (mainly loops vs. indexed arrays) +- Performance on creating StringTable has been increased +- Performance on writing Excel2007 worksheet has been increased + +## 2007-01-18 + +- Images can now be rotated +- Fixed bug: When drawings have full path specified, no mime type can be deducted +- Fixed bug: Only one drawing can be added to a worksheet + +## 2007-01-12 + +- Refactoring of some classes to use ArrayObject instead of array() +- Cell style now has support for number format (i.e. #,##0) +- Implemented embedding images + +## 2007-01-02 + +- Cell style now has support for fills, including gradient fills +- Cell style now has support for fonts +- Cell style now has support for border colors +- Cell style now has support for font colors +- Cell style now has support for alignment + +## 2006-12-21 + +- Support for cell style borders +- Support for cell styles +- Refactoring of Excel2007 Writer into multiple classes in package SpreadSheet_Writer_Excel2007 +- Refactoring of all classes, changed public members to public properties using getter/setter +- Worksheet names are now unique. On duplicate worksheet names, a number is appended. +- Worksheet now has parent SpreadSheet object +- Worksheet now has support for page header and footer +- Worksheet now has support for page margins +- Worksheet now has support for page setup (only Paper size and Orientation) +- Worksheet properties now accessible by using getProperties() +- Worksheet now has support for row and column dimensions (height / width) +- Exceptions thrown have a more clear description + +## Initial version + +- Create a Spreadsheet object +- Add one or more Worksheet objects +- Add cells to Worksheet objects +- Export Spreadsheet object to Excel 2007 OpenXML format +- Each cell supports the following data formats: string, number, formula, boolean. diff --git a/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.md b/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.md new file mode 100644 index 00000000000..897a8e51338 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/CHANGELOG.md @@ -0,0 +1,471 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com) +and this project adheres to [Semantic Versioning](https://semver.org). + +## [1.12.0] - 2020-04-27 + +### Added + +- Improved the ARABIC function to also handle short-hand roman numerals +- Added support for the FLOOR.MATH and FLOOR.PRECISE functions [#1351](https://github.com/PHPOffice/PhpSpreadsheet/pull/1351) + +### Fixed + +- Fix ROUNDUP and ROUNDDOWN for floating-point rounding error [#1404](https://github.com/PHPOffice/PhpSpreadsheet/pull/1404) +- Fix ROUNDUP and ROUNDDOWN for negative number [#1417](https://github.com/PHPOffice/PhpSpreadsheet/pull/1417) +- Fix loading styles from vmlDrawings when containing whitespace [#1347](https://github.com/PHPOffice/PhpSpreadsheet/issues/1347) +- Fix incorrect behavior when removing last row [#1365](https://github.com/PHPOffice/PhpSpreadsheet/pull/1365) +- MATCH with a static array should return the position of the found value based on the values submitted [#1332](https://github.com/PHPOffice/PhpSpreadsheet/pull/1332) +- Fix Xlsx Reader's handling of undefined fill color [#1353](https://github.com/PHPOffice/PhpSpreadsheet/pull/1353) + +## [1.11.0] - 2020-03-02 + +### Added + +- Added support for the BASE function +- Added support for the ARABIC function +- Conditionals - Extend Support for (NOT)CONTAINSBLANKS [#1278](https://github.com/PHPOffice/PhpSpreadsheet/pull/1278) + +### Fixed + +- Handle Error in Formula Processing Better for Xls [#1267](https://github.com/PHPOffice/PhpSpreadsheet/pull/1267) +- Handle ConditionalStyle NumberFormat When Reading Xlsx File [#1296](https://github.com/PHPOffice/PhpSpreadsheet/pull/1296) +- Fix Xlsx Writer's handling of decimal commas [#1282](https://github.com/PHPOffice/PhpSpreadsheet/pull/1282) +- Fix for issue by removing test code mistakenly left in [#1328](https://github.com/PHPOffice/PhpSpreadsheet/pull/1328) +- Fix for Xls writer wrong selected cells and active sheet [#1256](https://github.com/PHPOffice/PhpSpreadsheet/pull/1256) +- Fix active cell when freeze pane is used [#1323](https://github.com/PHPOffice/PhpSpreadsheet/pull/1323) +- Fix XLSX file loading with autofilter containing '$' [#1326](https://github.com/PHPOffice/PhpSpreadsheet/pull/1326) +- PHPDoc - Use `@return $this` for fluent methods [#1362](https://github.com/PHPOffice/PhpSpreadsheet/pull/1362) + +## [1.10.1] - 2019-12-02 + +### Changed + +- PHP 7.4 compatibility + +### Fixed + +- FLOOR() function accept negative number and negative significance [#1245](https://github.com/PHPOffice/PhpSpreadsheet/pull/1245) +- Correct column style even when using rowspan [#1249](https://github.com/PHPOffice/PhpSpreadsheet/pull/1249) +- Do not confuse defined names and cell refs [#1263](https://github.com/PHPOffice/PhpSpreadsheet/pull/1263) +- XLSX reader/writer keep decimal for floats with a zero decimal part [#1262](https://github.com/PHPOffice/PhpSpreadsheet/pull/1262) +- ODS writer prevent invalid numeric value if locale decimal separator is comma [#1268](https://github.com/PHPOffice/PhpSpreadsheet/pull/1268) +- Xlsx writer actually writes plotVisOnly and dispBlanksAs from chart properties [#1266](https://github.com/PHPOffice/PhpSpreadsheet/pull/1266) + +## [1.10.0] - 2019-11-18 + +### Changed + +- Change license from LGPL 2.1 to MIT [#140](https://github.com/PHPOffice/PhpSpreadsheet/issues/140) + +### Added + +- Implementation of IFNA() logical function +- Support "showZeros" worksheet option to change how Excel shows and handles "null" values returned from a calculation +- Allow HTML Reader to accept HTML as a string into an existing spreadsheet [#1212](https://github.com/PHPOffice/PhpSpreadsheet/pull/1212) + +### Fixed + +- IF implementation properly handles the value `#N/A` [#1165](https://github.com/PHPOffice/PhpSpreadsheet/pull/1165) +- Formula Parser: Wrong line count for stuff like "MyOtherSheet!A:D" [#1215](https://github.com/PHPOffice/PhpSpreadsheet/issues/1215) +- Call garbage collector after removing a column to prevent stale cached values +- Trying to remove a column that doesn't exist deletes the latest column +- Keep big integer as integer instead of lossely casting to float [#874](https://github.com/PHPOffice/PhpSpreadsheet/pull/874) +- Fix branch pruning handling of non boolean conditions [#1167](https://github.com/PHPOffice/PhpSpreadsheet/pull/1167) +- Fix ODS Reader when no DC namespace are defined [#1182](https://github.com/PHPOffice/PhpSpreadsheet/pull/1182) +- Fixed Functions->ifCondition for allowing <> and empty condition [#1206](https://github.com/PHPOffice/PhpSpreadsheet/pull/1206) +- Validate XIRR inputs and return correct error values [#1120](https://github.com/PHPOffice/PhpSpreadsheet/issues/1120) +- Allow to read xlsx files with exotic workbook names like "workbook2.xml" [#1183](https://github.com/PHPOffice/PhpSpreadsheet/pull/1183) + +## [1.9.0] - 2019-08-17 + +### Changed + +- Drop support for PHP 5.6 and 7.0, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support + +### Added + +- When <br> appears in a table cell, set the cell to wrap [#1071](https://github.com/PHPOffice/PhpSpreadsheet/issues/1071) and [#1070](https://github.com/PHPOffice/PhpSpreadsheet/pull/1070) +- Add MAXIFS, MINIFS, COUNTIFS and Remove MINIF, MAXIF [#1056](https://github.com/PHPOffice/PhpSpreadsheet/issues/1056) +- HLookup needs an ordered list even if range_lookup is set to false [#1055](https://github.com/PHPOffice/PhpSpreadsheet/issues/1055) and [#1076](https://github.com/PHPOffice/PhpSpreadsheet/pull/1076) +- Improve performance of IF function calls via ranch pruning to avoid resolution of every branches [#844](https://github.com/PHPOffice/PhpSpreadsheet/pull/844) +- MATCH function supports `*?~` Excel functionality, when match_type=0 [#1116](https://github.com/PHPOffice/PhpSpreadsheet/issues/1116) +- Allow HTML Reader to accept HTML as a string [#1136](https://github.com/PHPOffice/PhpSpreadsheet/pull/1136) + +### Fixed + +- Fix to AVERAGEIF() function when called with a third argument +- Eliminate duplicate fill none style entries [#1066](https://github.com/PHPOffice/PhpSpreadsheet/issues/1066) +- Fix number format masks containing literal (non-decimal point) dots [#1079](https://github.com/PHPOffice/PhpSpreadsheet/issues/1079) +- Fix number format masks containing named colours that were being misinterpreted as date formats; and add support for masks that fully replace the value with a full text string [#1009](https://github.com/PHPOffice/PhpSpreadsheet/issues/1009) +- Stricter-typed comparison testing in COUNTIF() and COUNTIFS() evaluation [#1046](https://github.com/PHPOffice/PhpSpreadsheet/issues/1046) +- COUPNUM should not return zero when settlement is in the last period [#1020](https://github.com/PHPOffice/PhpSpreadsheet/issues/1020) and [#1021](https://github.com/PHPOffice/PhpSpreadsheet/pull/1021) +- Fix handling of named ranges referencing sheets with spaces or "!" in their title +- Cover `getSheetByName()` with tests for name with quote and spaces [#739](https://github.com/PHPOffice/PhpSpreadsheet/issues/739) +- Best effort to support invalid colspan values in HTML reader - [#878](https://github.com/PHPOffice/PhpSpreadsheet/pull/878) +- Fixes incorrect rows deletion [#868](https://github.com/PHPOffice/PhpSpreadsheet/issues/868) +- MATCH function fix (value search by type, stop search when match_type=-1 and unordered element encountered) [#1116](https://github.com/PHPOffice/PhpSpreadsheet/issues/1116) +- Fix `getCalculatedValue()` error with more than two INDIRECT [#1115](https://github.com/PHPOffice/PhpSpreadsheet/pull/1115) +- Writer\Html did not hide columns [#985](https://github.com/PHPOffice/PhpSpreadsheet/pull/985) + +## [1.8.2] - 2019-07-08 + +### Fixed + +- Uncaught error when opening ods file and properties aren't defined [#1047](https://github.com/PHPOffice/PhpSpreadsheet/issues/1047) +- Xlsx Reader Cell datavalidations bug [#1052](https://github.com/PHPOffice/PhpSpreadsheet/pull/1052) + +## [1.8.1] - 2019-07-02 + +### Fixed + +- Allow nullable theme for Xlsx Style Reader class [#1043](https://github.com/PHPOffice/PhpSpreadsheet/issues/1043) + +## [1.8.0] - 2019-07-01 + +### Security Fix (CVE-2019-12331) + +- Detect double-encoded xml in the Security scanner, and reject as suspicious. +- This change also broadens the scope of the `libxml_disable_entity_loader` setting when reading XML-based formats, so that it is enabled while the xml is being parsed and not simply while it is loaded. + On some versions of PHP, this can cause problems because it is not thread-safe, and can affect other PHP scripts running on the same server. This flag is set to true when instantiating a loader, and back to its original setting when the Reader is no longer in scope, or manually unset. +- Provide a check to identify whether libxml_disable_entity_loader is thread-safe or not. + + `XmlScanner::threadSafeLibxmlDisableEntityLoaderAvailability()` +- Provide an option to disable the libxml_disable_entity_loader call through settings. This is not recommended as it reduces the security of the XML-based readers, and should only be used if you understand the consequences and have no other choice. + +### Added + +- Added support for the SWITCH function [#963](https://github.com/PHPOffice/PhpSpreadsheet/issues/963) and [#983](https://github.com/PHPOffice/PhpSpreadsheet/pull/983) +- Add accounting number format style [#974](https://github.com/PHPOffice/PhpSpreadsheet/pull/974) + +### Fixed + +- Whitelist `tsv` extension when opening CSV files [#429](https://github.com/PHPOffice/PhpSpreadsheet/issues/429) +- Fix a SUMIF warning with some versions of PHP when having different length of arrays provided as input [#873](https://github.com/PHPOffice/PhpSpreadsheet/pull/873) +- Fix incorrectly handled backslash-escaped space characters in number format + +## [1.7.0] - 2019-05-26 + +- Added support for inline styles in Html reader (borders, alignment, width, height) +- QuotedText cells no longer treated as formulae if the content begins with a `=` +- Clean handling for DDE in formulae + +### Fixed + +- Fix handling for escaped enclosures and new lines in CSV Separator Inference +- Fix MATCH an error was appearing when comparing strings against 0 (always true) +- Fix wrong calculation of highest column with specified row [#700](https://github.com/PHPOffice/PhpSpreadsheet/issues/700) +- Fix VLOOKUP +- Fix return type hint + +## [1.6.0] - 2019-01-02 + +### Added + +- Refactored Matrix Functions to use external Matrix library +- Possibility to specify custom colors of values for pie and donut charts [#768](https://github.com/PHPOffice/PhpSpreadsheet/pull/768) + +### Fixed + +- Improve XLSX parsing speed if no readFilter is applied [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772) +- Fix column names if read filter calls in XLSX reader skip columns [#777](https://github.com/PHPOffice/PhpSpreadsheet/pull/777) +- XLSX reader can now ignore blank cells, using the setReadEmptyCells(false) method. [#810](https://github.com/PHPOffice/PhpSpreadsheet/issues/810) +- Fix LOOKUP function which was breaking on edge cases [#796](https://github.com/PHPOffice/PhpSpreadsheet/issues/796) +- Fix VLOOKUP with exact matches [#809](https://github.com/PHPOffice/PhpSpreadsheet/pull/809) +- Support COUNTIFS multiple arguments [#830](https://github.com/PHPOffice/PhpSpreadsheet/pull/830) +- Change `libxml_disable_entity_loader()` as shortly as possible [#819](https://github.com/PHPOffice/PhpSpreadsheet/pull/819) +- Improved memory usage and performance when loading large spreadsheets [#822](https://github.com/PHPOffice/PhpSpreadsheet/pull/822) +- Improved performance when loading large spreadsheets [#825](https://github.com/PHPOffice/PhpSpreadsheet/pull/825) +- Improved performance when loading large spreadsheets [#824](https://github.com/PHPOffice/PhpSpreadsheet/pull/824) +- Fix color from CSS when reading from HTML [#831](https://github.com/PHPOffice/PhpSpreadsheet/pull/831) +- Fix infinite loop when reading invalid ODS files [#832](https://github.com/PHPOffice/PhpSpreadsheet/pull/832) +- Fix time format for duration is incorrect [#666](https://github.com/PHPOffice/PhpSpreadsheet/pull/666) +- Fix iconv unsupported `//IGNORE//TRANSLIT` on IBM i [#791](https://github.com/PHPOffice/PhpSpreadsheet/issues/791) + +### Changed + +- `master` is the new default branch, `develop` does not exist anymore + +## [1.5.2] - 2018-11-25 + +### Security + +- Improvements to the design of the XML Security Scanner [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771) + +## [1.5.1] - 2018-11-20 + +### Security + +- Fix and improve XXE security scanning for XML-based and HTML Readers [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771) + +### Added + +- Support page margin in mPDF [#750](https://github.com/PHPOffice/PhpSpreadsheet/issues/750) + +### Fixed + +- Support numeric condition in SUMIF, SUMIFS, AVERAGEIF, COUNTIF, MAXIF and MINIF [#683](https://github.com/PHPOffice/PhpSpreadsheet/issues/683) +- SUMIFS containing multiple conditions [#704](https://github.com/PHPOffice/PhpSpreadsheet/issues/704) +- Csv reader avoid notice when the file is empty [#743](https://github.com/PHPOffice/PhpSpreadsheet/pull/743) +- Fix print area parser for XLSX reader [#734](https://github.com/PHPOffice/PhpSpreadsheet/pull/734) +- Support overriding `DefaultValueBinder::dataTypeForValue()` without overriding `DefaultValueBinder::bindValue()` [#735](https://github.com/PHPOffice/PhpSpreadsheet/pull/735) +- Mpdf export can exceed pcre.backtrack_limit [#637](https://github.com/PHPOffice/PhpSpreadsheet/issues/637) +- Fix index overflow on data values array [#748](https://github.com/PHPOffice/PhpSpreadsheet/pull/748) + +## [1.5.0] - 2018-10-21 + +### Added + +- PHP 7.3 support +- Add the DAYS() function [#594](https://github.com/PHPOffice/PhpSpreadsheet/pull/594) + +### Fixed + +- Sheet title can contain exclamation mark [#325](https://github.com/PHPOffice/PhpSpreadsheet/issues/325) +- Xls file cause the exception during open by Xls reader [#402](https://github.com/PHPOffice/PhpSpreadsheet/issues/402) +- Skip non numeric value in SUMIF [#618](https://github.com/PHPOffice/PhpSpreadsheet/pull/618) +- OFFSET should allow omitted height and width [#561](https://github.com/PHPOffice/PhpSpreadsheet/issues/561) +- Correctly determine delimiter when CSV contains line breaks inside enclosures [#716](https://github.com/PHPOffice/PhpSpreadsheet/issues/716) + +## [1.4.1] - 2018-09-30 + +### Fixed + +- Remove locale from formatting string [#644](https://github.com/PHPOffice/PhpSpreadsheet/pull/644) +- Allow iterators to go out of bounds with prev [#587](https://github.com/PHPOffice/PhpSpreadsheet/issues/587) +- Fix warning when reading xlsx without styles [#631](https://github.com/PHPOffice/PhpSpreadsheet/pull/631) +- Fix broken sample links on windows due to $baseDir having backslash [#653](https://github.com/PHPOffice/PhpSpreadsheet/pull/653) + +## [1.4.0] - 2018-08-06 + +### Added + +- Add excel function EXACT(value1, value2) support [#595](https://github.com/PHPOffice/PhpSpreadsheet/pull/595) +- Support workbook view attributes for Xlsx format [#523](https://github.com/PHPOffice/PhpSpreadsheet/issues/523) +- Read and write hyperlink for drawing image [#490](https://github.com/PHPOffice/PhpSpreadsheet/pull/490) +- Added calculation engine support for the new bitwise functions that were added in MS Excel 2013 + - BITAND() Returns a Bitwise 'And' of two numbers + - BITOR() Returns a Bitwise 'Or' of two number + - BITXOR() Returns a Bitwise 'Exclusive Or' of two numbers + - BITLSHIFT() Returns a number shifted left by a specified number of bits + - BITRSHIFT() Returns a number shifted right by a specified number of bits +- Added calculation engine support for other new functions that were added in MS Excel 2013 and MS Excel 2016 + - Text Functions + - CONCAT() Synonym for CONCATENATE() + - NUMBERVALUE() Converts text to a number, in a locale-independent way + - UNICHAR() Synonym for CHAR() in PHPSpreadsheet, which has always used UTF-8 internally + - UNIORD() Synonym for ORD() in PHPSpreadsheet, which has always used UTF-8 internally + - TEXTJOIN() Joins together two or more text strings, separated by a delimiter + - Logical Functions + - XOR() Returns a logical Exclusive Or of all arguments + - Date/Time Functions + - ISOWEEKNUM() Returns the ISO 8601 week number of the year for a given date + - Lookup and Reference Functions + - FORMULATEXT() Returns a formula as a string + - Financial Functions + - PDURATION() Calculates the number of periods required for an investment to reach a specified value + - RRI() Calculates the interest rate required for an investment to grow to a specified future value + - Engineering Functions + - ERF.PRECISE() Returns the error function integrated between 0 and a supplied limit + - ERFC.PRECISE() Synonym for ERFC + - Math and Trig Functions + - SEC() Returns the secant of an angle + - SECH() Returns the hyperbolic secant of an angle + - CSC() Returns the cosecant of an angle + - CSCH() Returns the hyperbolic cosecant of an angle + - COT() Returns the cotangent of an angle + - COTH() Returns the hyperbolic cotangent of an angle + - ACOT() Returns the cotangent of an angle + - ACOTH() Returns the hyperbolic cotangent of an angle +- Refactored Complex Engineering Functions to use external complex number library +- Added calculation engine support for the new complex number functions that were added in MS Excel 2013 + - IMCOSH() Returns the hyperbolic cosine of a complex number + - IMCOT() Returns the cotangent of a complex number + - IMCSC() Returns the cosecant of a complex number + - IMCSCH() Returns the hyperbolic cosecant of a complex number + - IMSEC() Returns the secant of a complex number + - IMSECH() Returns the hyperbolic secant of a complex number + - IMSINH() Returns the hyperbolic sine of a complex number + - IMTAN() Returns the tangent of a complex number + +### Fixed + +- Fix ISFORMULA() function to work with a cell reference to another worksheet +- Xlsx reader crashed when reading a file with workbook protection [#553](https://github.com/PHPOffice/PhpSpreadsheet/pull/553) +- Cell formats with escaped spaces were causing incorrect date formatting [#557](https://github.com/PHPOffice/PhpSpreadsheet/issues/557) +- Could not open CSV file containing HTML fragment [#564](https://github.com/PHPOffice/PhpSpreadsheet/issues/564) +- Exclude the vendor folder in migration [#481](https://github.com/PHPOffice/PhpSpreadsheet/issues/481) +- Chained operations on cell ranges involving borders operated on last cell only [#428](https://github.com/PHPOffice/PhpSpreadsheet/issues/428) +- Avoid memory exhaustion when cloning worksheet with a drawing [#437](https://github.com/PHPOffice/PhpSpreadsheet/issues/437) +- Migration tool keep variables containing $PHPExcel untouched [#598](https://github.com/PHPOffice/PhpSpreadsheet/issues/598) +- Rowspans/colspans were incorrect when adding worksheet using loadIntoExisting [#619](https://github.com/PHPOffice/PhpSpreadsheet/issues/619) + +## [1.3.1] - 2018-06-12 + +### Fixed + +- Ranges across Z and AA columns incorrectly threw an exception [#545](https://github.com/PHPOffice/PhpSpreadsheet/issues/545) + +## [1.3.0] - 2018-06-10 + +### Added + +- Support to read Xlsm templates with form elements, macros, printer settings, protected elements and back compatibility drawing, and save result without losing important elements of document [#435](https://github.com/PHPOffice/PhpSpreadsheet/issues/435) +- Expose sheet title maximum length as `Worksheet::SHEET_TITLE_MAXIMUM_LENGTH` [#482](https://github.com/PHPOffice/PhpSpreadsheet/issues/482) +- Allow escape character to be set in CSV reader [#492](https://github.com/PHPOffice/PhpSpreadsheet/issues/492) + +### Fixed + +- Subtotal 9 in a group that has other subtotals 9 exclude the totals of the other subtotals in the range [#332](https://github.com/PHPOffice/PhpSpreadsheet/issues/332) +- `Helper\Html` support UTF-8 HTML input [#444](https://github.com/PHPOffice/PhpSpreadsheet/issues/444) +- Xlsx loaded an extra empty comment for each real comment [#375](https://github.com/PHPOffice/PhpSpreadsheet/issues/375) +- Xlsx reader do not read rows and columns filtered out in readFilter at all [#370](https://github.com/PHPOffice/PhpSpreadsheet/issues/370) +- Make newer Excel versions properly recalculate formulas on document open [#456](https://github.com/PHPOffice/PhpSpreadsheet/issues/456) +- `Coordinate::extractAllCellReferencesInRange()` throws an exception for an invalid range [#519](https://github.com/PHPOffice/PhpSpreadsheet/issues/519) +- Fixed parsing of conditionals in COUNTIF functions [#526](https://github.com/PHPOffice/PhpSpreadsheet/issues/526) +- Corruption errors for saved Xlsx docs with frozen panes [#532](https://github.com/PHPOffice/PhpSpreadsheet/issues/532) + +## [1.2.1] - 2018-04-10 + +### Fixed + +- Plain text and richtext mixed in same cell can be read [#442](https://github.com/PHPOffice/PhpSpreadsheet/issues/442) + +## [1.2.0] - 2018-03-04 + +### Added + +- HTML writer creates a generator meta tag [#312](https://github.com/PHPOffice/PhpSpreadsheet/issues/312) +- Support invalid zoom value in XLSX format [#350](https://github.com/PHPOffice/PhpSpreadsheet/pull/350) +- Support for `_xlfn.` prefixed functions and `ISFORMULA`, `MODE.SNGL`, `STDEV.S`, `STDEV.P` [#390](https://github.com/PHPOffice/PhpSpreadsheet/pull/390) + +### Fixed + +- Avoid potentially unsupported PSR-16 cache keys [#354](https://github.com/PHPOffice/PhpSpreadsheet/issues/354) +- Check for MIME type to know if CSV reader can read a file [#167](https://github.com/PHPOffice/PhpSpreadsheet/issues/167) +- Use proper € symbol for currency format [#379](https://github.com/PHPOffice/PhpSpreadsheet/pull/379) +- Read printing area correctly when skipping some sheets [#371](https://github.com/PHPOffice/PhpSpreadsheet/issues/371) +- Avoid incorrectly overwriting calculated value type [#394](https://github.com/PHPOffice/PhpSpreadsheet/issues/394) +- Select correct cell when calling freezePane [#389](https://github.com/PHPOffice/PhpSpreadsheet/issues/389) +- `setStrikethrough()` did not set the font [#403](https://github.com/PHPOffice/PhpSpreadsheet/issues/403) + +## [1.1.0] - 2018-01-28 + +### Added + +- Support for PHP 7.2 +- Support cell comments in HTML writer and reader [#308](https://github.com/PHPOffice/PhpSpreadsheet/issues/308) +- Option to stop at a conditional styling, if it matches (only XLSX format) [#292](https://github.com/PHPOffice/PhpSpreadsheet/pull/292) +- Support for line width for data series when rendering Xlsx [#329](https://github.com/PHPOffice/PhpSpreadsheet/pull/329) + +### Fixed + +- Better auto-detection of CSV separators [#305](https://github.com/PHPOffice/PhpSpreadsheet/issues/305) +- Support for shape style ending with `;` [#304](https://github.com/PHPOffice/PhpSpreadsheet/issues/304) +- Freeze Panes takes wrong coordinates for XLSX [#322](https://github.com/PHPOffice/PhpSpreadsheet/issues/322) +- `COLUMNS` and `ROWS` functions crashed in some cases [#336](https://github.com/PHPOffice/PhpSpreadsheet/issues/336) +- Support XML file without styles [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331) +- Cell coordinates which are already a range cause an exception [#319](https://github.com/PHPOffice/PhpSpreadsheet/issues/319) + +## [1.0.0] - 2017-12-25 + +### Added + +- Support to write merged cells in ODS format [#287](https://github.com/PHPOffice/PhpSpreadsheet/issues/287) +- Able to set the `topLeftCell` in freeze panes [#261](https://github.com/PHPOffice/PhpSpreadsheet/pull/261) +- Support `DateTimeImmutable` as cell value +- Support migration of prefixed classes + +### Fixed + +- Can read very small HTML files [#194](https://github.com/PHPOffice/PhpSpreadsheet/issues/194) +- Written DataValidation was corrupted [#290](https://github.com/PHPOffice/PhpSpreadsheet/issues/290) +- Date format compatible with both LibreOffice and Excel [#298](https://github.com/PHPOffice/PhpSpreadsheet/issues/298) + +### BREAKING CHANGE + +- Constant `TYPE_DOUGHTNUTCHART` is now `TYPE_DOUGHNUTCHART`. + +## [1.0.0-beta2] - 2017-11-26 + +### Added + +- Support for chart fill color - @CrazyBite [#158](https://github.com/PHPOffice/PhpSpreadsheet/pull/158) +- Support for read Hyperlink for xml - @GreatHumorist [#223](https://github.com/PHPOffice/PhpSpreadsheet/pull/223) +- Support for cell value validation according to data validation rules - @SailorMax [#257](https://github.com/PHPOffice/PhpSpreadsheet/pull/257) +- Support for custom implementation, or configuration, of PDF libraries - @SailorMax [#266](https://github.com/PHPOffice/PhpSpreadsheet/pull/266) + +### Changed + +- Merge data-validations to reduce written worksheet size - @billblume [#131](https://github.com/PHPOffice/PhpSpreadSheet/issues/131) +- Throws exception if a XML file is invalid - @GreatHumorist [#222](https://github.com/PHPOffice/PhpSpreadsheet/pull/222) +- Upgrade to mPDF 7.0+ [#144](https://github.com/PHPOffice/PhpSpreadsheet/issues/144) + +### Fixed + +- Control characters in cell values are automatically escaped [#212](https://github.com/PHPOffice/PhpSpreadsheet/issues/212) +- Prevent color changing when copy/pasting xls files written by PhpSpreadsheet to another file - @al-lala [#218](https://github.com/PHPOffice/PhpSpreadsheet/issues/218) +- Add cell reference automatic when there is no cell reference('r' attribute) in Xlsx file. - @GreatHumorist [#225](https://github.com/PHPOffice/PhpSpreadsheet/pull/225) Refer to [#201](https://github.com/PHPOffice/PhpSpreadsheet/issues/201) +- `Reader\Xlsx::getFromZipArchive()` function return false if the zip entry could not be located. - @anton-harvey [#268](https://github.com/PHPOffice/PhpSpreadsheet/pull/268) + +### BREAKING CHANGE + +- Extracted coordinate method to dedicate class [migration guide](./docs/topics/migration-from-PHPExcel.md). +- Column indexes are based on 1, see the [migration guide](./docs/topics/migration-from-PHPExcel.md). +- Standardization of array keys used for style, see the [migration guide](./docs/topics/migration-from-PHPExcel.md). +- Easier usage of PDF writers, and other custom readers and writers, see the [migration guide](./docs/topics/migration-from-PHPExcel.md). +- Easier usage of chart renderers, see the [migration guide](./docs/topics/migration-from-PHPExcel.md). +- Rename a few more classes to keep them in their related namespaces: + - `CalcEngine` => `Calculation\Engine` + - `PhpSpreadsheet\Calculation` => `PhpSpreadsheet\Calculation\Calculation` + - `PhpSpreadsheet\Cell` => `PhpSpreadsheet\Cell\Cell` + - `PhpSpreadsheet\Chart` => `PhpSpreadsheet\Chart\Chart` + - `PhpSpreadsheet\RichText` => `PhpSpreadsheet\RichText\RichText` + - `PhpSpreadsheet\Style` => `PhpSpreadsheet\Style\Style` + - `PhpSpreadsheet\Worksheet` => `PhpSpreadsheet\Worksheet\Worksheet` + +## [1.0.0-beta] - 2017-08-17 + +### Added + +- Initial implementation of SUMIFS() function +- Additional codepages +- MemoryDrawing not working in HTML writer [#808](https://github.com/PHPOffice/PHPExcel/issues/808) +- CSV Reader can auto-detect the separator used in file [#141](https://github.com/PHPOffice/PhpSpreadsheet/pull/141) +- HTML Reader supports some basic inline styles [#180](https://github.com/PHPOffice/PhpSpreadsheet/pull/180) + +### Changed + +- Start following [SemVer](https://semver.org) properly. + +### Fixed + +- Fix to getCell() method when cell reference includes a worksheet reference - @MarkBaker +- Ignore inlineStr type if formula element exists - @ncrypthic [#570](https://github.com/PHPOffice/PHPExcel/issues/570) +- Excel 2007 Reader freezes because of conditional formatting - @rentalhost [#575](https://github.com/PHPOffice/PHPExcel/issues/575) +- Readers will now parse files containing worksheet titles over 31 characters [#176](https://github.com/PHPOffice/PhpSpreadsheet/pull/176) + +### General + +- Whitespace after toRichTextObject() - @MarkBaker [#554](https://github.com/PHPOffice/PHPExcel/issues/554) +- Optimize vlookup() sort - @umpirsky [#548](https://github.com/PHPOffice/PHPExcel/issues/548) +- c:max and c:min elements shall NOT be inside c:orientation elements - @vitalyrepin [#869](https://github.com/PHPOffice/PHPExcel/pull/869) +- Implement actual timezone adjustment into PHPExcel_Shared_Date::PHPToExcel - @sim642 [#489](https://github.com/PHPOffice/PHPExcel/pull/489) + +### BREAKING CHANGE + +- Introduction of namespaces for all classes, eg: `PHPExcel_Calculation_Functions` becomes `PhpOffice\PhpSpreadsheet\Calculation\Functions` +- Some classes were renamed for clarity and/or consistency: + +For a comprehensive list of all class changes, and a semi-automated migration path, read the [migration guide](./docs/topics/migration-from-PHPExcel.md). + +- Dropped `PHPExcel_Calculation_Functions::VERSION()`. Composer or git should be used to know the version. +- Dropped `PHPExcel_Settings::setPdfRenderer()` and `PHPExcel_Settings::setPdfRenderer()`. Composer should be used to autoload PDF libs. +- Dropped support for HHVM + +## Previous versions of PHPExcel + +The changelog for the project when it was called PHPExcel is [still available](./CHANGELOG.PHPExcel.md). diff --git a/htdocs/includes/phpoffice/phpspreadsheet/CONTRIBUTING.md b/htdocs/includes/phpoffice/phpspreadsheet/CONTRIBUTING.md new file mode 100644 index 00000000000..aed13fe2db2 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Want to contribute? + +If you would like to contribute, here are some notes and guidelines: + + - All new development happens on feature/fix branches, and are then merged to the `master` branch once stable; so the `master` branch is always the most up-to-date, working code + - Tagged releases are made from the `master` branch + - If you are going to be submitting a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number + - Code style might be automatically fixed by `composer fix` + - All code changes must be validated by `composer check` + - [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository") + - [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests") diff --git a/htdocs/includes/phpoffice/phpspreadsheet/LICENSE b/htdocs/includes/phpoffice/phpspreadsheet/LICENSE new file mode 100644 index 00000000000..3ec5723dde1 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 PhpSpreadsheet Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/htdocs/includes/phpoffice/phpspreadsheet/composer.json b/htdocs/includes/phpoffice/phpspreadsheet/composer.json new file mode 100644 index 00000000000..cfff1cb1ab3 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/composer.json @@ -0,0 +1,86 @@ +{ + "name": "phpoffice/phpspreadsheet", + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "keywords": ["PHP", "OpenXML", "Excel", "xlsx", "xls", "ods", "gnumeric", "spreadsheet"], + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "scripts": { + "check": [ + "php-cs-fixer fix --ansi --dry-run --diff", + "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n", + "phpunit --color=always" + ], + "fix": [ + "php-cs-fixer fix --ansi" + ], + "versions": [ + "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PHPCompatibility --runtime-set testVersion 7.1- -n" + ] + }, + "require": { + "php": "^7.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-fileinfo": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-SimpleXML": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "markbaker/complex": "^1.4", + "markbaker/matrix": "^1.2", + "psr/simple-cache": "^1.0" + }, + "require-dev": { + "dompdf/dompdf": "^0.8.3", + "friendsofphp/php-cs-fixer": "^2.16", + "jpgraph/jpgraph": "^4.0", + "mpdf/mpdf": "^8.0", + "phpcompatibility/php-compatibility": "^9.3", + "phpunit/phpunit": "^7.5", + "squizlabs/php_codesniffer": "^3.5", + "tecnickcom/tcpdf": "^6.3" + }, + "suggest": { + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer", + "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers" + }, + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "autoload-dev": { + "psr-4": { + "PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests" + } + } +} diff --git a/htdocs/includes/phpoffice/phpspreadsheet/composer.lock b/htdocs/includes/phpoffice/phpspreadsheet/composer.lock new file mode 100644 index 00000000000..9299919f5de --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/composer.lock @@ -0,0 +1,3503 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "0fd32acfbb0d21f168f495840ffc8d7e", + "packages": [ + { + "name": "markbaker/complex", + "version": "1.4.7", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/1ea674a8308baf547cbcbd30c5fcd6d301b7c000", + "reference": "1ea674a8308baf547cbcbd30c5fcd6d301b7c000", + "shasum": "" + }, + "require": { + "php": "^5.6.0|^7.0.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", + "phpcompatibility/php-compatibility": "^8.0", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "2.*", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.35|^5.4.0", + "sebastian/phpcpd": "2.*", + "squizlabs/php_codesniffer": "^3.3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + }, + "files": [ + "classes/src/functions/abs.php", + "classes/src/functions/acos.php", + "classes/src/functions/acosh.php", + "classes/src/functions/acot.php", + "classes/src/functions/acoth.php", + "classes/src/functions/acsc.php", + "classes/src/functions/acsch.php", + "classes/src/functions/argument.php", + "classes/src/functions/asec.php", + "classes/src/functions/asech.php", + "classes/src/functions/asin.php", + "classes/src/functions/asinh.php", + "classes/src/functions/atan.php", + "classes/src/functions/atanh.php", + "classes/src/functions/conjugate.php", + "classes/src/functions/cos.php", + "classes/src/functions/cosh.php", + "classes/src/functions/cot.php", + "classes/src/functions/coth.php", + "classes/src/functions/csc.php", + "classes/src/functions/csch.php", + "classes/src/functions/exp.php", + "classes/src/functions/inverse.php", + "classes/src/functions/ln.php", + "classes/src/functions/log2.php", + "classes/src/functions/log10.php", + "classes/src/functions/negative.php", + "classes/src/functions/pow.php", + "classes/src/functions/rho.php", + "classes/src/functions/sec.php", + "classes/src/functions/sech.php", + "classes/src/functions/sin.php", + "classes/src/functions/sinh.php", + "classes/src/functions/sqrt.php", + "classes/src/functions/tan.php", + "classes/src/functions/tanh.php", + "classes/src/functions/theta.php", + "classes/src/operations/add.php", + "classes/src/operations/subtract.php", + "classes/src/operations/multiply.php", + "classes/src/operations/divideby.php", + "classes/src/operations/divideinto.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "time": "2018-10-13T23:28:42+00:00" + }, + { + "name": "markbaker/matrix", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "5348c5a67e3b75cd209d70103f916a93b1f1ed21" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/5348c5a67e3b75cd209d70103f916a93b1f1ed21", + "reference": "5348c5a67e3b75cd209d70103f916a93b1f1ed21", + "shasum": "" + }, + "require": { + "php": "^5.6.0|^7.0.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "dev-master", + "phploc/phploc": "^4", + "phpmd/phpmd": "dev-master", + "phpunit/phpunit": "^5.7", + "sebastian/phpcpd": "^3.0", + "squizlabs/php_codesniffer": "^3.0@dev" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + }, + "files": [ + "classes/src/functions/adjoint.php", + "classes/src/functions/antidiagonal.php", + "classes/src/functions/cofactors.php", + "classes/src/functions/determinant.php", + "classes/src/functions/diagonal.php", + "classes/src/functions/identity.php", + "classes/src/functions/inverse.php", + "classes/src/functions/minors.php", + "classes/src/functions/trace.php", + "classes/src/functions/transpose.php", + "classes/src/operations/add.php", + "classes/src/operations/directsum.php", + "classes/src/operations/subtract.php", + "classes/src/operations/multiply.php", + "classes/src/operations/divideby.php", + "classes/src/operations/divideinto.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "time": "2019-10-06T11:29:25+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/semver", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2019-03-19T17:25:45+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "cbe23383749496fe0f373345208b79568e4bc248" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/cbe23383749496fe0f373345208b79568e4bc248", + "reference": "cbe23383749496fe0f373345208b79568e4bc248", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-11-06T16:40:04+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2019-10-01T18:55:10+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "a2c590166b2133a4633738648b6b064edae0814a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-03-17T17:37:11+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-06-08T11:03:04+00:00" + }, + { + "name": "dompdf/dompdf", + "version": "v0.8.3", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "75f13c700009be21a1965dc2c5b68a8708c22ba2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/75f13c700009be21a1965dc2c5b68a8708c22ba2", + "reference": "75f13c700009be21a1965dc2c5b68a8708c22ba2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "phenx/php-font-lib": "0.5.*", + "phenx/php-svg-lib": "0.3.*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.5|^6.5", + "squizlabs/php_codesniffer": "2.*" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + }, + { + "name": "Brian Sweeney", + "email": "eclecticgeek@gmail.com" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "time": "2018-12-14T02:40:31+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.16.1", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c8afb599858876e95e8ebfcd97812d383fa23f02", + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02", + "shasum": "" + }, + "require": { + "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.2", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^5.6 || ^7.0", + "php-cs-fixer/diff": "^1.3", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.2", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.1", + "php-cs-fixer/accessible-object": "^1.0", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", + "phpunitgoodpractices/traits": "^1.8", + "symfony/phpunit-bridge": "^4.3 || ^5.0", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationCaseFactory.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/Test/IntegrationCaseFactoryInterface.php", + "tests/Test/InternalIntegrationCaseFactory.php", + "tests/TestCase.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz RumiÅ„ski", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2019-11-25T22:10:32+00:00" + }, + { + "name": "jpgraph/jpgraph", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/ztec/JpGraph.git", + "reference": "e82db7da6a546d3926c24c9a346226da7aa49094" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ztec/JpGraph/zipball/e82db7da6a546d3926c24c9a346226da7aa49094", + "reference": "e82db7da6a546d3926c24c9a346226da7aa49094", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/JpGraph.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "QPL 1.0" + ], + "authors": [ + { + "name": "JpGraph team" + } + ], + "description": "jpGraph, library to make graphs and charts", + "homepage": "http://jpgraph.net/", + "keywords": [ + "chart", + "data", + "graph", + "jpgraph", + "pie" + ], + "time": "2017-02-23T09:44:15+00:00" + }, + { + "name": "mpdf/mpdf", + "version": "v8.0.4", + "source": { + "type": "git", + "url": "https://github.com/mpdf/mpdf.git", + "reference": "d3147a0d790b6d11936fd9c73fa31a7ed45e3f6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/d3147a0d790b6d11936fd9c73fa31a7ed45e3f6f", + "reference": "d3147a0d790b6d11936fd9c73fa31a7ed45e3f6f", + "shasum": "" + }, + "require": { + "ext-gd": "*", + "ext-mbstring": "*", + "myclabs/deep-copy": "^1.7", + "paragonie/random_compat": "^1.4|^2.0|9.99.99", + "php": "^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0", + "psr/log": "^1.0", + "setasign/fpdi": "^2.1" + }, + "require-dev": { + "mockery/mockery": "^0.9.5", + "mpdf/qrcode": "^1.0.0", + "phpunit/phpunit": "^5.0", + "squizlabs/php_codesniffer": "^3.5.0", + "tracy/tracy": "^2.4" + }, + "suggest": { + "ext-bcmath": "Needed for generation of some types of barcodes", + "ext-xml": "Needed mainly for SVG manipulation", + "ext-zlib": "Needed for compression of embedded resources, such as fonts" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-development": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Mpdf\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-only" + ], + "authors": [ + { + "name": "MatÄ›j Humpál", + "role": "Developer, maintainer" + }, + { + "name": "Ian Back", + "role": "Developer (retired)" + } + ], + "description": "PHP library generating PDF files from UTF-8 encoded HTML", + "homepage": "https://mpdf.github.io", + "keywords": [ + "pdf", + "php", + "utf-8" + ], + "time": "2019-11-28T09:39:33+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2019-08-09T12:45:53+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phenx/php-font-lib", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/PhenX/php-font-lib.git", + "reference": "760148820110a1ae0936e5cc35851e25a938bc97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/760148820110a1ae0936e5cc35851e25a938bc97", + "reference": "760148820110a1ae0936e5cc35851e25a938bc97", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", + "time": "2017-09-13T16:14:37+00:00" + }, + { + "name": "phenx/php-svg-lib", + "version": "v0.3.3", + "source": { + "type": "git", + "url": "https://github.com/PhenX/php-svg-lib.git", + "reference": "5fa61b65e612ce1ae15f69b3d223cb14ecc60e32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/5fa61b65e612ce1ae15f69b3d223cb14ecc60e32", + "reference": "5fa61b65e612ce1ae15f69b3d223cb14ecc60e32", + "shasum": "" + }, + "require": { + "sabberworm/php-css-parser": "^8.3" + }, + "require-dev": { + "phpunit/phpunit": "^5.5|^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", + "time": "2019-09-11T20:02:13+00:00" + }, + { + "name": "php-cs-fixer/diff", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", + "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "symfony/process": "^3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "SpacePossum" + } + ], + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", + "keywords": [ + "diff" + ], + "time": "2018-02-15T16:58:55+00:00" + }, + { + "name": "phpcompatibility/php-compatibility", + "version": "9.3.2", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/bfca2be3992f40e92206e5a7ebe5eaee37280b58", + "reference": "bfca2be3992f40e92206e5a7ebe5eaee37280b58", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards" + ], + "time": "2019-10-16T21:24:24+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2018-08-07T13:53:10+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-09-12T14:27:41+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "shasum": "" + }, + "require": { + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2019-10-03T11:07:50+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1 || ^4.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2018-10-31T16:06:48+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "050bedf145a257b1ff02746c31894800e5122946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2018-09-13T20:33:42+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2019-06-07T04:22:29+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2019-09-17T06:23:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.5.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4c92a15296e58191a4cd74cff3b34fc8e374174a", + "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2019-10-28T10:37:36+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/log", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-01T11:05:21+00:00" + }, + { + "name": "sabberworm/php-css-parser", + "version": "8.3.0", + "source": { + "type": "git", + "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", + "reference": "91bcc3e3fdb7386c9a2e0e0aa09ca75cc43f121f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/91bcc3e3fdb7386c9a2e0e0aa09ca75cc43f121f", + "reference": "91bcc3e3fdb7386c9a2e0e0aa09ca75cc43f121f", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "codacy/coverage": "^1.4", + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "autoload": { + "psr-0": { + "Sabberworm\\CSS": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "time": "2019-02-22T07:42:52+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2019-02-04T06:01:07+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2019-05-05T09:05:15+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2019-09-14T09:02:43+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2018-10-04T04:07:39+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "setasign/fpdi", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/Setasign/FPDI.git", + "reference": "3c266002f8044f61b17329f7cd702d44d73f0f7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/3c266002f8044f61b17329f7cd702d44d73f0f7f", + "reference": "3c266002f8044f61b17329f7cd702d44d73f0f7f", + "shasum": "" + }, + "require": { + "ext-zlib": "*", + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "~5.7", + "setasign/fpdf": "~1.8", + "setasign/tfpdf": "1.25", + "tecnickcom/tcpdf": "~6.2" + }, + "suggest": { + "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured.", + "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.", + "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF.", + "setasign/fpdi-tfpdf": "Use this package to automatically evaluate dependencies to tFPDF." + }, + "type": "library", + "autoload": { + "psr-4": { + "setasign\\Fpdi\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Slabon", + "email": "jan.slabon@setasign.com", + "homepage": "https://www.setasign.com" + }, + { + "name": "Maximilian Kresse", + "email": "maximilian.kresse@setasign.com", + "homepage": "https://www.setasign.com" + } + ], + "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", + "homepage": "https://www.setasign.com/fpdi", + "keywords": [ + "fpdf", + "fpdi", + "pdf" + ], + "time": "2019-01-30T14:11:19+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.5.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2019-10-28T04:36:32+00:00" + }, + { + "name": "symfony/console", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/136c4bd62ea871d00843d1bc0316de4c4a84bb78", + "reference": "136c4bd62ea871d00843d1bc0316de4c4a84bb78", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/var-dumper": "^4.3" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-10-30T12:58:49+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "^3.4|^4.0", + "symfony/service-contracts": "^1.1", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-10-01T16:40:32+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-09-17T09:54:03+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-08-20T14:07:54+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/72a068f77e317ae77c0a0495236ad292cfb5ce6f", + "reference": "72a068f77e317ae77c0a0495236ad292cfb5ce6f", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-10-30T12:53:54+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "f46c7fc8e207bd8a2188f54f8738f232533765a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/f46c7fc8e207bd8a2188f54f8738f232533765a4", + "reference": "f46c7fc8e207bd8a2188f54f8738f232533765a4", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2019-10-28T20:59:01+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "54b4c428a0054e254223797d2713c31e08610831" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/54b4c428a0054e254223797d2713c31e08610831", + "reference": "54b4c428a0054e254223797d2713c31e08610831", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0|~9.99", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "04ce3335667451138df4307d6a9b61565560199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/process", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "3b2e0cb029afbb0395034509291f21191d1a4db0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/3b2e0cb029afbb0395034509291f21191d1a4db0", + "reference": "3b2e0cb029afbb0395034509291f21191d1a4db0", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2019-10-28T17:07:32+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v1.1.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffc7f5692092df31515df2a5ecf3b7302b3ddacf", + "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-10-14T12:27:06+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v4.3.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e4ff456bd625be5032fac9be4294e60442e9b71", + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/service-contracts": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Stopwatch Component", + "homepage": "https://symfony.com", + "time": "2019-08-07T11:52:19+00:00" + }, + { + "name": "tecnickcom/tcpdf", + "version": "6.3.2", + "source": { + "type": "git", + "url": "https://github.com/tecnickcom/TCPDF.git", + "reference": "9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b", + "reference": "9fde7bb9b404b945e7ea88fb7eccd23d9a4e324b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "config", + "include", + "tcpdf.php", + "tcpdf_parser.php", + "tcpdf_import.php", + "tcpdf_barcodes_1d.php", + "tcpdf_barcodes_2d.php", + "include/tcpdf_colors.php", + "include/tcpdf_filters.php", + "include/tcpdf_font_data.php", + "include/tcpdf_fonts.php", + "include/tcpdf_images.php", + "include/tcpdf_static.php", + "include/barcodes/datamatrix.php", + "include/barcodes/pdf417.php", + "include/barcodes/qrcode.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Nicola Asuni", + "email": "info@tecnick.com", + "role": "lead" + } + ], + "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", + "homepage": "http://www.tcpdf.org/", + "keywords": [ + "PDFD32000-2008", + "TCPDF", + "barcodes", + "datamatrix", + "pdf", + "pdf417", + "qrcode" + ], + "time": "2019-09-20T09:35:01+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-08-24T08:43:50+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-fileinfo": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*" + }, + "platform-dev": [] +} diff --git a/htdocs/includes/phpoffice/phpspreadsheet/mkdocs.yml b/htdocs/includes/phpoffice/phpspreadsheet/mkdocs.yml new file mode 100644 index 00000000000..cf87a142a33 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/mkdocs.yml @@ -0,0 +1,7 @@ +site_name: PhpSpreadsheet Documentation +repo_url: https://github.com/PHPOffice/phpspreadsheet +edit_uri: edit/master/docs/ + +theme: readthedocs +extra_css: + - extra/extra.css diff --git a/htdocs/includes/phpoffice/phpspreadsheet/phpunit.xml.dist b/htdocs/includes/phpoffice/phpspreadsheet/phpunit.xml.dist new file mode 100644 index 00000000000..be3643d8a41 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/phpunit.xml.dist @@ -0,0 +1,23 @@ + + + + + + + ./tests/PhpSpreadsheetTests + + + + ./src + + ./src/PhpSpreadsheet/Shared/JAMA + ./src/PhpSpreadsheet/Writer/PDF + + + + diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/Bootstrap.php b/htdocs/includes/phpoffice/phpspreadsheet/src/Bootstrap.php new file mode 100644 index 00000000000..f15de26a6c4 --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/Bootstrap.php @@ -0,0 +1,22 @@ +=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})'; + const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?\b([a-z]{1,3})\$?(\d{1,7})(?![\w.])'; // Named Range of cells const CALCULATION_REGEXP_NAMEDRANGE = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)'; // Error @@ -66,6 +66,15 @@ class Calculation */ private $calculationCacheEnabled = true; + /** + * Used to generate unique store keys. + * + * @var int + */ + private $branchStoreKeyCounter = 0; + + private $branchPruningEnabled = true; + /** * List of operators that can be used within formulae * The true/false value indicates whether it is a binary operator or a unary operator. @@ -254,6 +263,11 @@ class Calculation 'functionCall' => [Logical::class, 'logicalAnd'], 'argumentCount' => '1+', ], + 'ARABIC' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'ARABIC'], + 'argumentCount' => '1', + ], 'AREAS' => [ 'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => [Functions::class, 'DUMMY'], @@ -319,6 +333,11 @@ class Calculation 'functionCall' => [Functions::class, 'DUMMY'], 'argumentCount' => '1', ], + 'BASE' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'BASE'], + 'argumentCount' => '2,3', + ], 'BESSELI' => [ 'category' => Category::CATEGORY_ENGINEERING, 'functionCall' => [Engineering::class, 'BESSELI'], @@ -527,7 +546,7 @@ class Calculation ], 'COUNTIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Functions::class, 'DUMMY'], + 'functionCall' => [Statistical::class, 'COUNTIFS'], 'argumentCount' => '2+', ], 'COUPDAYBS' => [ @@ -895,6 +914,16 @@ class Calculation 'functionCall' => [MathTrig::class, 'FLOOR'], 'argumentCount' => '2', ], + 'FLOOR.MATH' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'FLOORMATH'], + 'argumentCount' => '3', + ], + 'FLOOR.PRECISE' => [ + 'category' => Category::CATEGORY_MATH_AND_TRIG, + 'functionCall' => [MathTrig::class, 'FLOORPRECISE'], + 'argumentCount' => '2', + ], 'FORECAST' => [ 'category' => Category::CATEGORY_STATISTICAL, 'functionCall' => [Statistical::class, 'FORECAST'], @@ -1018,6 +1047,16 @@ class Calculation 'functionCall' => [Logical::class, 'IFERROR'], 'argumentCount' => '2', ], + 'IFNA' => [ + 'category' => Category::CATEGORY_LOGICAL, + 'functionCall' => [Logical::class, 'IFNA'], + 'argumentCount' => '2', + ], + 'IFS' => [ + 'category' => Category::CATEGORY_LOGICAL, + 'functionCall' => [Functions::class, 'DUMMY'], + 'argumentCount' => '2+', + ], 'IMABS' => [ 'category' => Category::CATEGORY_ENGINEERING, 'functionCall' => [Engineering::class, 'IMABS'], @@ -1356,10 +1395,10 @@ class Calculation 'functionCall' => [Statistical::class, 'MAXA'], 'argumentCount' => '1+', ], - 'MAXIF' => [ + 'MAXIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MAXIF'], - 'argumentCount' => '2+', + 'functionCall' => [Statistical::class, 'MAXIFS'], + 'argumentCount' => '3+', ], 'MDETERM' => [ 'category' => Category::CATEGORY_MATH_AND_TRIG, @@ -1401,10 +1440,10 @@ class Calculation 'functionCall' => [Statistical::class, 'MINA'], 'argumentCount' => '1+', ], - 'MINIF' => [ + 'MINIFS' => [ 'category' => Category::CATEGORY_STATISTICAL, - 'functionCall' => [Statistical::class, 'MINIF'], - 'argumentCount' => '2+', + 'functionCall' => [Statistical::class, 'MINIFS'], + 'argumentCount' => '3+', ], 'MINUTE' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, @@ -1474,7 +1513,12 @@ class Calculation 'NETWORKDAYS' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, 'functionCall' => [DateTime::class, 'NETWORKDAYS'], - 'argumentCount' => '2+', + 'argumentCount' => '2-3', + ], + 'NETWORKDAYS.INTL' => [ + 'category' => Category::CATEGORY_DATE_AND_TIME, + 'functionCall' => [Functions::class, 'DUMMY'], + 'argumentCount' => '2-4', ], 'NOMINAL' => [ 'category' => Category::CATEGORY_FINANCIAL, @@ -2143,7 +2187,12 @@ class Calculation 'WORKDAY' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, 'functionCall' => [DateTime::class, 'WORKDAY'], - 'argumentCount' => '2+', + 'argumentCount' => '2-3', + ], + 'WORKDAY.INTL' => [ + 'category' => Category::CATEGORY_DATE_AND_TIME, + 'functionCall' => [Functions::class, 'DUMMY'], + 'argumentCount' => '2-4', ], 'XIRR' => [ 'category' => Category::CATEGORY_FINANCIAL, @@ -2196,7 +2245,7 @@ class Calculation private static $controlFunctions = [ 'MKMATRIX' => [ 'argumentCount' => '*', - 'functionCall' => 'self::mkMatrix', + 'functionCall' => [__CLASS__, 'mkMatrix'], ], ]; @@ -2251,6 +2300,7 @@ class Calculation public function flushInstance() { $this->clearCalculationCache(); + $this->clearBranchStore(); } /** @@ -2394,6 +2444,32 @@ class Calculation } } + /** + * Enable/disable calculation cache. + * + * @param bool $pValue + * @param mixed $enabled + */ + public function setBranchPruningEnabled($enabled) + { + $this->branchPruningEnabled = $enabled; + } + + public function enableBranchPruning() + { + $this->setBranchPruningEnabled(true); + } + + public function disableBranchPruning() + { + $this->setBranchPruningEnabled(false); + } + + public function clearBranchStore() + { + $this->branchStoreKeyCounter = 0; + } + /** * Get the currently defined locale code. * @@ -2416,7 +2492,7 @@ class Calculation // Identify our locale and language $language = $locale = strtolower($locale); if (strpos($locale, '_') !== false) { - list($language) = explode('_', $locale); + [$language] = explode('_', $locale); } if (count(self::$validLocaleLanguages) == 1) { self::loadLocales(); @@ -2441,9 +2517,9 @@ class Calculation // Retrieve the list of locale or language specific function names $localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($localeFunctions as $localeFunction) { - list($localeFunction) = explode('##', $localeFunction); // Strip out comments + [$localeFunction] = explode('##', $localeFunction); // Strip out comments if (strpos($localeFunction, '=') !== false) { - list($fName, $lfName) = explode('=', $localeFunction); + [$fName, $lfName] = explode('=', $localeFunction); $fName = trim($fName); $lfName = trim($lfName); if ((isset(self::$phpSpreadsheetFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) { @@ -2466,9 +2542,9 @@ class Calculation if (file_exists($configFile)) { $localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($localeSettings as $localeSetting) { - list($localeSetting) = explode('##', $localeSetting); // Strip out comments + [$localeSetting] = explode('##', $localeSetting); // Strip out comments if (strpos($localeSetting, '=') !== false) { - list($settingName, $settingValue) = explode('=', $localeSetting); + [$settingName, $settingValue] = explode('=', $localeSetting); $settingName = strtoupper(trim($settingName)); switch ($settingName) { case 'ARGUMENTSEPARATOR': @@ -2772,7 +2848,7 @@ class Calculation } self::$returnArrayAsType = $returnArrayAsType; - if ($result === null) { + if ($result === null && $pCell->getWorksheet()->getSheetView()->getShowZeros()) { return 0; } elseif ((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) { return Functions::NAN(); @@ -2823,13 +2899,13 @@ class Calculation $this->debugLog->clearLog(); $this->cyclicReferenceStack->clear(); + $resetCache = $this->getCalculationCacheEnabled(); if ($this->spreadsheet !== null && $cellID === null && $pCell === null) { $cellID = 'A1'; $pCell = $this->spreadsheet->getActiveSheet()->getCell($cellID); } else { // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache - $resetCache = $this->getCalculationCacheEnabled(); $this->calculationCacheEnabled = false; } @@ -2862,6 +2938,7 @@ class Calculation if (($this->calculationCacheEnabled) && (isset($this->calculationCache[$cellReference]))) { $this->debugLog->writeDebugLog('Retrieving value for cell ', $cellReference, ' from cache'); // Return the cached result + $cellValue = $this->calculationCache[$cellReference]; return true; @@ -2977,17 +3054,17 @@ class Calculation // Examine each of the two operands, and turn them into an array if they aren't one already // Note that this function should only be called if one or both of the operand is already an array if (!is_array($operand1)) { - list($matrixRows, $matrixColumns) = self::getMatrixDimensions($operand2); + [$matrixRows, $matrixColumns] = self::getMatrixDimensions($operand2); $operand1 = array_fill(0, $matrixRows, array_fill(0, $matrixColumns, $operand1)); $resize = 0; } elseif (!is_array($operand2)) { - list($matrixRows, $matrixColumns) = self::getMatrixDimensions($operand1); + [$matrixRows, $matrixColumns] = self::getMatrixDimensions($operand1); $operand2 = array_fill(0, $matrixRows, array_fill(0, $matrixColumns, $operand2)); $resize = 0; } - list($matrix1Rows, $matrix1Columns) = self::getMatrixDimensions($operand1); - list($matrix2Rows, $matrix2Columns) = self::getMatrixDimensions($operand2); + [$matrix1Rows, $matrix1Columns] = self::getMatrixDimensions($operand1); + [$matrix2Rows, $matrix2Columns] = self::getMatrixDimensions($operand2); if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) { $resize = 1; } @@ -3197,7 +3274,7 @@ class Calculation /** * @param string $formula * - * @return string + * @return false|string False indicates an error */ private function convertMatrixReferences($formula) { @@ -3321,9 +3398,53 @@ class Calculation // - is a negation or + is a positive operator rather than an operation $expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand // should be null in a function call + + // IF branch pruning + // currently pending storeKey (last item of the storeKeysStack + $pendingStoreKey = null; + // stores a list of storeKeys (string[]) + $pendingStoreKeysStack = []; + $expectingConditionMap = []; // ['storeKey' => true, ...] + $expectingThenMap = []; // ['storeKey' => true, ...] + $expectingElseMap = []; // ['storeKey' => true, ...] + $parenthesisDepthMap = []; // ['storeKey' => 4, ...] + // The guts of the lexical parser // Loop through the formula extracting each operator and operand in turn while (true) { + // Branch pruning: we adapt the output item to the context (it will + // be used to limit its computation) + $currentCondition = null; + $currentOnlyIf = null; + $currentOnlyIfNot = null; + $previousStoreKey = null; + $pendingStoreKey = end($pendingStoreKeysStack); + + if ($this->branchPruningEnabled) { + // this is a condition ? + if (isset($expectingConditionMap[$pendingStoreKey]) && $expectingConditionMap[$pendingStoreKey]) { + $currentCondition = $pendingStoreKey; + $stackDepth = count($pendingStoreKeysStack); + if ($stackDepth > 1) { // nested if + $previousStoreKey = $pendingStoreKeysStack[$stackDepth - 2]; + } + } + if (isset($expectingThenMap[$pendingStoreKey]) && $expectingThenMap[$pendingStoreKey]) { + $currentOnlyIf = $pendingStoreKey; + } elseif (isset($previousStoreKey)) { + if (isset($expectingThenMap[$previousStoreKey]) && $expectingThenMap[$previousStoreKey]) { + $currentOnlyIf = $previousStoreKey; + } + } + if (isset($expectingElseMap[$pendingStoreKey]) && $expectingElseMap[$pendingStoreKey]) { + $currentOnlyIfNot = $pendingStoreKey; + } elseif (isset($previousStoreKey)) { + if (isset($expectingElseMap[$previousStoreKey]) && $expectingElseMap[$previousStoreKey]) { + $currentOnlyIfNot = $previousStoreKey; + } + } + } + $opCharacter = $formula[$index]; // Get the first character of the value at the current index position if ((isset(self::$comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$comparisonOperators[$formula[$index + 1]]))) { $opCharacter .= $formula[++$index]; @@ -3333,10 +3454,12 @@ class Calculation $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match); if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? - $stack->push('Unary Operator', '~'); // Put a negation on the stack + // Put a negation on the stack + $stack->push('Unary Operator', '~', null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); ++$index; // and drop the negation symbol } elseif ($opCharacter == '%' && $expectingOperator) { - $stack->push('Unary Operator', '%'); // Put a percentage on the stack + // Put a percentage on the stack + $stack->push('Unary Operator', '%', null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); ++$index; } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded? ++$index; // Drop the redundant plus symbol @@ -3349,7 +3472,10 @@ class Calculation @(self::$operatorAssociativity[$opCharacter] ? self::$operatorPrecedence[$opCharacter] < self::$operatorPrecedence[$o2['value']] : self::$operatorPrecedence[$opCharacter] <= self::$operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } - $stack->push('Binary Operator', $opCharacter); // Finally put our current operator onto the stack + + // Finally put our current operator onto the stack + $stack->push('Binary Operator', $opCharacter, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); + ++$index; $expectingOperator = false; } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis? @@ -3361,7 +3487,29 @@ class Calculation $output[] = $o2; } $d = $stack->last(2); - if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? + + // Branch pruning we decrease the depth whether is it a function + // call or a parenthesis + if (!empty($pendingStoreKey)) { + $parenthesisDepthMap[$pendingStoreKey] -= 1; + } + + if (is_array($d) && preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? + if (!empty($pendingStoreKey) && $parenthesisDepthMap[$pendingStoreKey] == -1) { + // we are closing an IF( + if ($d['value'] != 'IF(') { + return $this->raiseFormulaError('Parser bug we should be in an "IF("'); + } + if ($expectingConditionMap[$pendingStoreKey]) { + return $this->raiseFormulaError('We should not be expecting a condition'); + } + $expectingThenMap[$pendingStoreKey] = false; + $expectingElseMap[$pendingStoreKey] = false; + $parenthesisDepthMap[$pendingStoreKey] -= 1; + array_pop($pendingStoreKeysStack); + unset($pendingStoreKey); + } + $functionName = $matches[1]; // Get the function name $d = $stack->pop(); $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack) @@ -3422,6 +3570,20 @@ class Calculation } ++$index; } elseif ($opCharacter == ',') { // Is this the separator for function arguments? + if (!empty($pendingStoreKey) && + $parenthesisDepthMap[$pendingStoreKey] == 0 + ) { + // We must go to the IF next argument + if ($expectingConditionMap[$pendingStoreKey]) { + $expectingConditionMap[$pendingStoreKey] = false; + $expectingThenMap[$pendingStoreKey] = true; + } elseif ($expectingThenMap[$pendingStoreKey]) { + $expectingThenMap[$pendingStoreKey] = false; + $expectingElseMap[$pendingStoreKey] = true; + } elseif ($expectingElseMap[$pendingStoreKey]) { + return $this->raiseFormulaError('Reaching fourth argument of an IF'); + } + } while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if ($o2 === null) { return $this->raiseFormulaError('Formula Error: Unexpected ,'); @@ -3439,13 +3601,19 @@ class Calculation return $this->raiseFormulaError('Formula Error: Unexpected ,'); } $d = $stack->pop(); - $stack->push($d['type'], ++$d['value'], $d['reference']); // increment the argument count - $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again + $itemStoreKey = $d['storeKey'] ?? null; + $itemOnlyIf = $d['onlyIf'] ?? null; + $itemOnlyIfNot = $d['onlyIfNot'] ?? null; + $stack->push($d['type'], ++$d['value'], $d['reference'], $itemStoreKey, $itemOnlyIf, $itemOnlyIfNot); // increment the argument count + $stack->push('Brace', '(', null, $itemStoreKey, $itemOnlyIf, $itemOnlyIfNot); // put the ( back on, we'll need to pop back to it again $expectingOperator = false; $expectingOperand = true; ++$index; } elseif ($opCharacter == '(' && !$expectingOperator) { - $stack->push('Brace', '('); + if (!empty($pendingStoreKey)) { // Branch pruning: we go deeper + $parenthesisDepthMap[$pendingStoreKey] += 1; + } + $stack->push('Brace', '(', null, $currentCondition, $currentOnlyIf, $currentOnlyIf); ++$index; } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number? $expectingOperator = true; @@ -3456,13 +3624,28 @@ class Calculation if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $val, $matches)) { $val = preg_replace('/\s/u', '', $val); if (isset(self::$phpSpreadsheetFunctions[strtoupper($matches[1])]) || isset(self::$controlFunctions[strtoupper($matches[1])])) { // it's a function - $stack->push('Function', strtoupper($val)); + $valToUpper = strtoupper($val); + // here $matches[1] will contain values like "IF" + // and $val "IF(" + if ($this->branchPruningEnabled && ($valToUpper == 'IF(')) { // we handle a new if + $pendingStoreKey = $this->getUnusedBranchStoreKey(); + $pendingStoreKeysStack[] = $pendingStoreKey; + $expectingConditionMap[$pendingStoreKey] = true; + $parenthesisDepthMap[$pendingStoreKey] = 0; + } else { // this is not a if but we good deeper + if (!empty($pendingStoreKey) && array_key_exists($pendingStoreKey, $parenthesisDepthMap)) { + $parenthesisDepthMap[$pendingStoreKey] += 1; + } + } + + $stack->push('Function', $valToUpper, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); + // tests if the function is closed right after opening $ax = preg_match('/^\s*(\s*\))/ui', substr($formula, $index + $length), $amatch); if ($ax) { - $stack->push('Operand Count for Function ' . strtoupper($val) . ')', 0); + $stack->push('Operand Count for Function ' . $valToUpper . ')', 0, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); $expectingOperator = true; } else { - $stack->push('Operand Count for Function ' . strtoupper($val) . ')', 1); + $stack->push('Operand Count for Function ' . $valToUpper . ')', 1, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); $expectingOperator = false; } $stack->push('Brace', '('); @@ -3475,7 +3658,7 @@ class Calculation // If the last entry on the stack was a : operator, then we have a cell range reference $testPrevOp = $stack->last(1); - if ($testPrevOp['value'] == ':') { + if ($testPrevOp !== null && $testPrevOp['value'] == ':') { // If we have a worksheet reference, then we're playing with a 3D reference if ($matches[2] == '') { // Otherwise, we 'inherit' the worksheet reference from the start cell reference @@ -3490,32 +3673,39 @@ class Calculation } } - $output[] = ['type' => 'Cell Reference', 'value' => $val, 'reference' => $val]; + $outputItem = $stack->getStackItem('Cell Reference', $val, $val, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); + + $output[] = $outputItem; } else { // it's a variable, constant, string, number or boolean // If the last entry on the stack was a : operator, then we may have a row or column range reference $testPrevOp = $stack->last(1); - if ($testPrevOp['value'] == ':') { + if ($testPrevOp !== null && $testPrevOp['value'] === ':') { $startRowColRef = $output[count($output) - 1]['value']; - list($rangeWS1, $startRowColRef) = Worksheet::extractSheetTitle($startRowColRef, true); + [$rangeWS1, $startRowColRef] = Worksheet::extractSheetTitle($startRowColRef, true); + $rangeSheetRef = $rangeWS1; if ($rangeWS1 != '') { $rangeWS1 .= '!'; } - list($rangeWS2, $val) = Worksheet::extractSheetTitle($val, true); + [$rangeWS2, $val] = Worksheet::extractSheetTitle($val, true); if ($rangeWS2 != '') { $rangeWS2 .= '!'; } else { $rangeWS2 = $rangeWS1; } + $refSheet = $pCellParent; + if ($pCellParent !== null && $rangeSheetRef !== $pCellParent->getTitle()) { + $refSheet = $pCellParent->getParent()->getSheetByName($rangeSheetRef); + } if ((is_int($startRowColRef)) && (ctype_digit($val)) && ($startRowColRef <= 1048576) && ($val <= 1048576)) { // Row range - $endRowColRef = ($pCellParent !== null) ? $pCellParent->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007 + $endRowColRef = ($refSheet !== null) ? $refSheet->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007 $output[count($output) - 1]['value'] = $rangeWS1 . 'A' . $startRowColRef; $val = $rangeWS2 . $endRowColRef . $val; } elseif ((ctype_alpha($startRowColRef)) && (ctype_alpha($val)) && (strlen($startRowColRef) <= 3) && (strlen($val) <= 3)) { // Column range - $endRowColRef = ($pCellParent !== null) ? $pCellParent->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007 + $endRowColRef = ($refSheet !== null) ? $refSheet->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007 $output[count($output) - 1]['value'] = $rangeWS1 . strtoupper($startRowColRef) . '1'; $val = $rangeWS2 . $val . $endRowColRef; } @@ -3537,7 +3727,7 @@ class Calculation } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$localeBoolean)) !== false) { $val = self::$excelConstants[$localeConstant]; } - $details = ['type' => 'Value', 'value' => $val, 'reference' => null]; + $details = $stack->getStackItem('Value', $val, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); if ($localeConstant) { $details['localeValue'] = $localeConstant; } @@ -3557,7 +3747,7 @@ class Calculation } elseif (isset(self::$operators[$opCharacter]) && !$expectingOperator) { return $this->raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'"); } else { // I don't even want to know what you did to get here - return $this->raiseFormulaError('Formula Error: An unexpected error occured'); + return $this->raiseFormulaError('Formula Error: An unexpected error occurred'); } // Test for end of formula string if ($index == strlen($formula)) { @@ -3640,9 +3830,85 @@ class Calculation $pCellParent = ($pCell !== null) ? $pCell->getParent() : null; $stack = new Stack(); + // Stores branches that have been pruned + $fakedForBranchPruning = []; + // help us to know when pruning ['branchTestId' => true/false] + $branchStore = []; + // Loop through each token in turn foreach ($tokens as $tokenData) { $token = $tokenData['value']; + + // Branch pruning: skip useless resolutions + $storeKey = $tokenData['storeKey'] ?? null; + if ($this->branchPruningEnabled && isset($tokenData['onlyIf'])) { + $onlyIfStoreKey = $tokenData['onlyIf']; + $storeValue = $branchStore[$onlyIfStoreKey] ?? null; + $storeValueAsBool = ($storeValue === null) ? + true : (bool) Functions::flattenSingleValue($storeValue); + if (is_array($storeValue)) { + $wrappedItem = end($storeValue); + $storeValue = end($wrappedItem); + } + + if (isset($storeValue) + && ( + !$storeValueAsBool + || Functions::isError($storeValue) + || ($storeValue === 'Pruned branch') + ) + ) { + // If branching value is not true, we don't need to compute + if (!isset($fakedForBranchPruning['onlyIf-' . $onlyIfStoreKey])) { + $stack->push('Value', 'Pruned branch (only if ' . $onlyIfStoreKey . ') ' . $token); + $fakedForBranchPruning['onlyIf-' . $onlyIfStoreKey] = true; + } + + if (isset($storeKey)) { + // We are processing an if condition + // We cascade the pruning to the depending branches + $branchStore[$storeKey] = 'Pruned branch'; + $fakedForBranchPruning['onlyIfNot-' . $storeKey] = true; + $fakedForBranchPruning['onlyIf-' . $storeKey] = true; + } + + continue; + } + } + + if ($this->branchPruningEnabled && isset($tokenData['onlyIfNot'])) { + $onlyIfNotStoreKey = $tokenData['onlyIfNot']; + $storeValue = $branchStore[$onlyIfNotStoreKey] ?? null; + $storeValueAsBool = ($storeValue === null) ? + true : (bool) Functions::flattenSingleValue($storeValue); + if (is_array($storeValue)) { + $wrappedItem = end($storeValue); + $storeValue = end($wrappedItem); + } + if (isset($storeValue) + && ( + $storeValueAsBool + || Functions::isError($storeValue) + || ($storeValue === 'Pruned branch')) + ) { + // If branching value is true, we don't need to compute + if (!isset($fakedForBranchPruning['onlyIfNot-' . $onlyIfNotStoreKey])) { + $stack->push('Value', 'Pruned branch (only if not ' . $onlyIfNotStoreKey . ') ' . $token); + $fakedForBranchPruning['onlyIfNot-' . $onlyIfNotStoreKey] = true; + } + + if (isset($storeKey)) { + // We are processing an if condition + // We cascade the pruning to the depending branches + $branchStore[$storeKey] = 'Pruned branch'; + $fakedForBranchPruning['onlyIfNot-' . $storeKey] = true; + $fakedForBranchPruning['onlyIf-' . $storeKey] = true; + } + + continue; + } + } + // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack if (isset(self::$binaryOperators[$token])) { // We must have two operands, error if we don't @@ -3672,18 +3938,21 @@ class Calculation case '<=': // Less than or Equal to case '=': // Equality case '<>': // Inequality - $this->executeBinaryComparisonOperation($cellID, $operand1, $operand2, $token, $stack); + $result = $this->executeBinaryComparisonOperation($cellID, $operand1, $operand2, $token, $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; // Binary Operators case ':': // Range if (strpos($operand1Data['reference'], '!') !== false) { - list($sheet1, $operand1Data['reference']) = Worksheet::extractSheetTitle($operand1Data['reference'], true); + [$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true); } else { $sheet1 = ($pCellParent !== null) ? $pCellWorksheet->getTitle() : ''; } - list($sheet2, $operand2Data['reference']) = Worksheet::extractSheetTitle($operand2Data['reference'], true); + [$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true); if (empty($sheet2)) { $sheet2 = $sheet1; } @@ -3728,23 +3997,38 @@ class Calculation break; case '+': // Addition - $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'plusEquals', $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'plusEquals', $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; case '-': // Subtraction - $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'minusEquals', $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'minusEquals', $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; case '*': // Multiplication - $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayTimesEquals', $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayTimesEquals', $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; case '/': // Division - $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayRightDivide', $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayRightDivide', $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; case '^': // Exponential - $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'power', $stack); + $result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'power', $stack); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } break; case '&': // Concatenation @@ -3777,6 +4061,10 @@ class Calculation $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result)); $stack->push('Value', $result); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } + break; case '|': // Intersect $rowIntersect = array_intersect_key($operand1, $operand2); @@ -3821,6 +4109,9 @@ class Calculation } $this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result)); $stack->push('Value', $result); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } } else { $this->executeNumericBinaryOperation($multiplier, $arg, '*', 'arrayTimesEquals', $stack); } @@ -3894,9 +4185,16 @@ class Calculation } } $stack->push('Value', $cellValue, $cellRef); + if (isset($storeKey)) { + $branchStore[$storeKey] = $cellValue; + } - // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on + // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on } elseif (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $token, $matches)) { + if ($pCellParent) { + $pCell->attach($pCellParent); + } + $functionName = $matches[1]; $argCount = $stack->pop(); $argCount = $argCount['value']; @@ -3939,6 +4237,7 @@ class Calculation } } } + // Reverse the order of the arguments krsort($args); @@ -3963,22 +4262,32 @@ class Calculation } unset($arg); } + $result = call_user_func_array($functionCall, $args); if ($functionName != 'MKMATRIX') { $this->debugLog->writeDebugLog('Evaluation Result for ', self::localeFunc($functionName), '() function call is ', $this->showTypeDetails($result)); } $stack->push('Value', self::wrapResult($result)); + if (isset($storeKey)) { + $branchStore[$storeKey] = $result; + } } } else { // if the token is a number, boolean, string or an Excel error, push it onto the stack if (isset(self::$excelConstants[strtoupper($token)])) { $excelConstant = strtoupper($token); $stack->push('Constant Value', self::$excelConstants[$excelConstant]); + if (isset($storeKey)) { + $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] == '#')) { $stack->push('Value', $token); - // if the token is a named range, push the named range name onto the stack + if (isset($storeKey)) { + $branchStore[$storeKey] = $token; + } + // if the token is a named range, push the named range name onto the stack } elseif (preg_match('/^' . self::CALCULATION_REGEXP_NAMEDRANGE . '$/i', $token, $matches)) { $namedRange = $matches[6]; $this->debugLog->writeDebugLog('Evaluating Named Range ', $namedRange); @@ -3987,6 +4296,9 @@ class Calculation $pCell->attach($pCellParent); $this->debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->showTypeDetails($cellValue)); $stack->push('Named Range', $cellValue, $namedRange); + if (isset($storeKey)) { + $branchStore[$storeKey] = $cellValue; + } } else { return $this->raiseFormulaError("undefined variable '$token'"); } @@ -4048,7 +4360,7 @@ class Calculation * @param Stack $stack * @param bool $recursingArrays * - * @return bool + * @return mixed */ private function executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, Stack &$stack, $recursingArrays = false) { @@ -4085,7 +4397,7 @@ class Calculation // And push the result onto the stack $stack->push('Array', $result); - return true; + return $result; } // Simple validate the two operands if they are string values @@ -4175,7 +4487,7 @@ class Calculation // And push the result onto the stack $stack->push('Value', $result); - return true; + return $result; } /** @@ -4201,7 +4513,7 @@ class Calculation * @param string $matrixFunction * @param mixed $stack * - * @return bool + * @return bool|mixed */ private function executeNumericBinaryOperation($operand1, $operand2, $operation, $matrixFunction, &$stack) { @@ -4279,7 +4591,7 @@ class Calculation // And push the result onto the stack $stack->push('Value', $result); - return true; + return $result; } // trigger an error, but nicely, if need be @@ -4312,7 +4624,7 @@ class Calculation if ($pSheet !== null) { $pSheetName = $pSheet->getTitle(); if (strpos($pRange, '!') !== false) { - list($pSheetName, $pRange) = Worksheet::extractSheetTitle($pRange, true); + [$pSheetName, $pRange] = Worksheet::extractSheetTitle($pRange, true); $pSheet = $this->spreadsheet->getSheetByName($pSheetName); } @@ -4365,7 +4677,7 @@ class Calculation if ($pSheet !== null) { $pSheetName = $pSheet->getTitle(); if (strpos($pRange, '!') !== false) { - list($pSheetName, $pRange) = Worksheet::extractSheetTitle($pRange, true); + [$pSheetName, $pRange] = Worksheet::extractSheetTitle($pRange, true); $pSheet = $this->spreadsheet->getSheetByName($pSheetName); } @@ -4389,7 +4701,7 @@ class Calculation $aReferences = Coordinate::extractAllCellReferencesInRange($pRange); if (!isset($aReferences[1])) { // Single cell (or single column or row) in range - list($currentCol, $currentRow) = Coordinate::coordinateFromString($aReferences[0]); + [$currentCol, $currentRow] = Coordinate::coordinateFromString($aReferences[0]); if ($pSheet->cellExists($aReferences[0])) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); } else { @@ -4399,7 +4711,7 @@ class Calculation // Extract cell data for all cells in the range foreach ($aReferences as $reference) { // Extract range - list($currentCol, $currentRow) = Coordinate::coordinateFromString($reference); + [$currentCol, $currentRow] = Coordinate::coordinateFromString($reference); if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); } else { @@ -4483,4 +4795,26 @@ class Calculation return $args; } + + private function getUnusedBranchStoreKey() + { + $storeKeyValue = 'storeKey-' . $this->branchStoreKeyCounter; + ++$this->branchStoreKeyCounter; + + return $storeKeyValue; + } + + private function getTokensAsString($tokens) + { + $tokensStr = array_map(function ($token) { + $value = $token['value'] ?? 'no value'; + while (is_array($value)) { + $value = array_pop($value); + } + + return $value; + }, $tokens); + + return '[ ' . implode(' | ', $tokensStr) . ' ]'; + } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database.php index f6d9d8bb4bf..d31b00dd7df 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database.php @@ -147,7 +147,7 @@ class Database * the column label in which you specify a condition for the * column. * - * @return float + * @return float|string */ public static function DAVERAGE($database, $field, $criteria) { @@ -452,7 +452,7 @@ class Database * the column label in which you specify a condition for the * column. * - * @return float + * @return float|string */ public static function DSTDEV($database, $field, $criteria) { @@ -493,7 +493,7 @@ class Database * the column label in which you specify a condition for the * column. * - * @return float + * @return float|string */ public static function DSTDEVP($database, $field, $criteria) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTime.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTime.php index 3c39db2af7f..4f85edeb9c0 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTime.php @@ -16,7 +16,7 @@ class DateTime */ public static function isLeapYear($year) { - return (($year % 4) == 0) && (($year % 100) != 0) || (($year % 400) == 0); + return (($year % 4) === 0) && (($year % 100) !== 0) || (($year % 400) === 0); } /** @@ -156,11 +156,11 @@ class DateTime $retValue = (float) Date::PHPToExcel(time()); break; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: $retValue = (int) time(); break; - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: $retValue = new \DateTime(); break; @@ -200,11 +200,11 @@ class DateTime $retValue = (float) $excelDateTime; break; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: $retValue = (int) Date::excelToTimestamp($excelDateTime); break; - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: $retValue = Date::excelToDateTimeObject($excelDateTime); break; @@ -325,9 +325,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) $excelDateValue; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp($excelDateValue); - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return Date::excelToDateTimeObject($excelDateValue); } } @@ -420,9 +420,9 @@ class DateTime } return (float) Date::formattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second); - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp(Date::formattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; // -2147472000 + 3600 - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: $dayAdjust = 0; if ($hour < 0) { $dayAdjust = floor($hour / 24); @@ -472,7 +472,6 @@ class DateTime */ public static function DATEVALUE($dateValue = 1) { - $dateValueOrig = $dateValue; $dateValue = trim(Functions::flattenSingleValue($dateValue), '"'); // Strip any ordinals because they're allowed in Excel (English only) $dateValue = preg_replace('/(\d)(st|nd|rd|th)([ -\/])/Ui', '$1$3', $dateValue); @@ -492,7 +491,7 @@ class DateTime $yearFound = true; } } - if ((count($t1) == 1) && (strpos($t, ':') != false)) { + if ((count($t1) == 1) && (strpos($t, ':') !== false)) { // We've been fed a time value without any date return 0.0; } elseif (count($t1) == 2) { @@ -569,9 +568,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) $excelDateValue; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp($excelDateValue); - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return new \DateTime($PHPDateArray['year'] . '-' . $PHPDateArray['month'] . '-' . $PHPDateArray['day'] . ' 00:00:00'); } } @@ -631,9 +630,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) $excelDateValue; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) $phpDateValue = Date::excelToTimestamp($excelDateValue + 25569) - 3600; - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return new \DateTime('1900-01-01 ' . $PHPDateArray['hour'] . ':' . $PHPDateArray['minute'] . ':' . $PHPDateArray['second']); } } @@ -683,7 +682,6 @@ class DateTime $endMonths = $PHPEndDateObject->format('n'); $endYears = $PHPEndDateObject->format('Y'); - $retVal = Functions::NAN(); switch ($unit) { case 'D': $retVal = (int) $difference; @@ -880,6 +878,8 @@ class DateTime * * Excel Function: * YEARFRAC(startDate,endDate[,method]) + * See https://lists.oasis-open.org/archives/office-formula/200806/msg00039.html + * for description of algorithm used in Excel * * @category Date/Time Functions * @@ -894,7 +894,7 @@ class DateTime * 3 Actual/365 * 4 European 30/360 * - * @return float fraction of the year + * @return float|string fraction of the year, or a string containing an error */ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { @@ -908,6 +908,11 @@ class DateTime if (is_string($endDate = self::getDateValue($endDate))) { return Functions::VALUE(); } + if ($startDate > $endDate) { + $temp = $startDate; + $startDate = $endDate; + $endDate = $temp; + } if (((is_numeric($method)) && (!is_string($method))) || ($method == '')) { switch ($method) { @@ -918,46 +923,43 @@ class DateTime $startYear = self::YEAR($startDate); $endYear = self::YEAR($endDate); $years = $endYear - $startYear + 1; - $leapDays = 0; + $startMonth = self::MONTHOFYEAR($startDate); + $startDay = self::DAYOFMONTH($startDate); + $endMonth = self::MONTHOFYEAR($endDate); + $endDay = self::DAYOFMONTH($endDate); + $startMonthDay = 100 * $startMonth + $startDay; + $endMonthDay = 100 * $endMonth + $endDay; if ($years == 1) { if (self::isLeapYear($endYear)) { - $startMonth = self::MONTHOFYEAR($startDate); - $endMonth = self::MONTHOFYEAR($endDate); - $endDay = self::DAYOFMONTH($endDate); - if (($startMonth < 3) || - (($endMonth * 100 + $endDay) >= (2 * 100 + 29))) { - $leapDays += 1; + $tmpCalcAnnualBasis = 366; + } else { + $tmpCalcAnnualBasis = 365; + } + } elseif ($years == 2 && $startMonthDay >= $endMonthDay) { + if (self::isLeapYear($startYear)) { + if ($startMonthDay <= 229) { + $tmpCalcAnnualBasis = 366; + } else { + $tmpCalcAnnualBasis = 365; } + } elseif (self::isLeapYear($endYear)) { + if ($endMonthDay >= 229) { + $tmpCalcAnnualBasis = 366; + } else { + $tmpCalcAnnualBasis = 365; + } + } else { + $tmpCalcAnnualBasis = 365; } } else { + $tmpCalcAnnualBasis = 0; for ($year = $startYear; $year <= $endYear; ++$year) { - if ($year == $startYear) { - $startMonth = self::MONTHOFYEAR($startDate); - $startDay = self::DAYOFMONTH($startDate); - if ($startMonth < 3) { - $leapDays += (self::isLeapYear($year)) ? 1 : 0; - } - } elseif ($year == $endYear) { - $endMonth = self::MONTHOFYEAR($endDate); - $endDay = self::DAYOFMONTH($endDate); - if (($endMonth * 100 + $endDay) >= (2 * 100 + 29)) { - $leapDays += (self::isLeapYear($year)) ? 1 : 0; - } - } else { - $leapDays += (self::isLeapYear($year)) ? 1 : 0; - } + $tmpCalcAnnualBasis += self::isLeapYear($year) ? 366 : 365; } - if ($years == 2) { - if (($leapDays == 0) && (self::isLeapYear($startYear)) && ($days > 365)) { - $leapDays = 1; - } elseif ($days < 366) { - $years = 1; - } - } - $leapDays /= $years; + $tmpCalcAnnualBasis /= $years; } - return $days / (365 + $leapDays); + return $days / $tmpCalcAnnualBasis; case 2: return self::DATEDIF($startDate, $endDate) / 360; case 3: @@ -1154,9 +1156,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) $endDate; - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp($endDate); - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return Date::excelToDateTimeObject($endDate); } } @@ -1239,7 +1241,7 @@ class DateTime // Execute function $PHPDateObject = Date::excelToDateTimeObject($dateValue); - $DoW = $PHPDateObject->format('w'); + $DoW = (int) $PHPDateObject->format('w'); $firstDay = 1; switch ($style) { @@ -1248,13 +1250,13 @@ class DateTime break; case 2: - if ($DoW == 0) { + if ($DoW === 0) { $DoW = 7; } break; case 3: - if ($DoW == 0) { + if ($DoW === 0) { $DoW = 7; } $firstDay = 0; @@ -1272,9 +1274,39 @@ class DateTime } } - return (int) $DoW; + return $DoW; } + const STARTWEEK_SUNDAY = 1; + const STARTWEEK_MONDAY = 2; + const STARTWEEK_MONDAY_ALT = 11; + const STARTWEEK_TUESDAY = 12; + const STARTWEEK_WEDNESDAY = 13; + const STARTWEEK_THURSDAY = 14; + const STARTWEEK_FRIDAY = 15; + const STARTWEEK_SATURDAY = 16; + const STARTWEEK_SUNDAY_ALT = 17; + const DOW_SUNDAY = 1; + const DOW_MONDAY = 2; + const DOW_TUESDAY = 3; + const DOW_WEDNESDAY = 4; + const DOW_THURSDAY = 5; + const DOW_FRIDAY = 6; + const DOW_SATURDAY = 7; + const STARTWEEK_MONDAY_ISO = 21; + const METHODARR = [ + self::STARTWEEK_SUNDAY => self::DOW_SUNDAY, + self::DOW_MONDAY, + self::STARTWEEK_MONDAY_ALT => self::DOW_MONDAY, + self::DOW_TUESDAY, + self::DOW_WEDNESDAY, + self::DOW_THURSDAY, + self::DOW_FRIDAY, + self::DOW_SATURDAY, + self::DOW_SUNDAY, + self::STARTWEEK_MONDAY_ISO => self::STARTWEEK_MONDAY_ISO, + ]; + /** * WEEKNUM. * @@ -1293,41 +1325,51 @@ class DateTime * @param int $method Week begins on Sunday or Monday * 1 or omitted Week begins on Sunday. * 2 Week begins on Monday. + * 11 Week begins on Monday. + * 12 Week begins on Tuesday. + * 13 Week begins on Wednesday. + * 14 Week begins on Thursday. + * 15 Week begins on Friday. + * 16 Week begins on Saturday. + * 17 Week begins on Sunday. + * 21 ISO (Jan. 4 is week 1, begins on Monday). * * @return int|string Week Number */ - public static function WEEKNUM($dateValue = 1, $method = 1) + public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) { $dateValue = Functions::flattenSingleValue($dateValue); $method = Functions::flattenSingleValue($method); if (!is_numeric($method)) { return Functions::VALUE(); - } elseif (($method < 1) || ($method > 2)) { - return Functions::NAN(); } - $method = floor($method); + $method = (int) $method; + if (!array_key_exists($method, self::METHODARR)) { + return Functions::NaN(); + } + $method = self::METHODARR[$method]; - if ($dateValue === null) { - $dateValue = 1; - } elseif (is_string($dateValue = self::getDateValue($dateValue))) { + $dateValue = self::getDateValue($dateValue); + if (is_string($dateValue)) { return Functions::VALUE(); - } elseif ($dateValue < 0.0) { + } + if ($dateValue < 0.0) { return Functions::NAN(); } // Execute function $PHPDateObject = Date::excelToDateTimeObject($dateValue); + if ($method == self::STARTWEEK_MONDAY_ISO) { + return (int) $PHPDateObject->format('W'); + } $dayOfYear = $PHPDateObject->format('z'); $PHPDateObject->modify('-' . $dayOfYear . ' days'); $firstDayOfFirstWeek = $PHPDateObject->format('w'); $daysInFirstWeek = (6 - $firstDayOfFirstWeek + $method) % 7; - $interval = $dayOfYear - $daysInFirstWeek; - $weekOfYear = floor($interval / 7) + 1; - - if ($daysInFirstWeek) { - ++$weekOfYear; - } + $daysInFirstWeek += 7 * !$daysInFirstWeek; + $endFirstWeek = $daysInFirstWeek - 1; + $weekOfYear = floor(($dayOfYear - $endFirstWeek + 13) / 7); return (int) $weekOfYear; } @@ -1591,9 +1633,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) Date::PHPToExcel($PHPDateObject); - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp(Date::PHPToExcel($PHPDateObject)); - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return $PHPDateObject; } } @@ -1640,9 +1682,9 @@ class DateTime switch (Functions::getReturnDateType()) { case Functions::RETURNDATE_EXCEL: return (float) Date::PHPToExcel($PHPDateObject); - case Functions::RETURNDATE_PHP_NUMERIC: + case Functions::RETURNDATE_UNIX_TIMESTAMP: return (int) Date::excelToTimestamp(Date::PHPToExcel($PHPDateObject)); - case Functions::RETURNDATE_PHP_OBJECT: + case Functions::RETURNDATE_PHP_DATETIME_OBJECT: return $PHPDateObject; } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php index 3f1b48bd74c..c3942b2b2b3 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering.php @@ -785,7 +785,7 @@ class Engineering * If $ord is nonnumeric, BESSELI returns the #VALUE! error value. * If $ord < 0, BESSELI returns the #NUM! error value. * - * @return float + * @return float|string Result, or a string containing an error */ public static function BESSELI($x, $ord) { @@ -839,7 +839,7 @@ class Engineering * If $ord is nonnumeric, BESSELJ returns the #VALUE! error value. * If $ord < 0, BESSELJ returns the #NUM! error value. * - * @return float + * @return float|string Result, or a string containing an error */ public static function BESSELJ($x, $ord) { @@ -932,7 +932,7 @@ class Engineering * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. * If $ord < 0, BESSELK returns the #NUM! error value. * - * @return float + * @return float|string Result, or a string containing an error */ public static function BESSELK($x, $ord) { @@ -1021,7 +1021,7 @@ class Engineering * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. * If $ord < 0, BESSELK returns the #NUM! error value. * - * @return float + * @return float|string Result, or a string containing an error */ public static function BESSELY($x, $ord) { @@ -2713,7 +2713,7 @@ class Engineering * @param string $fromUOM the units for value * @param string $toUOM the units for the result * - * @return float + * @return float|string */ public static function CONVERTUOM($value, $fromUOM, $toUOM) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php index 3cb6d40a52e..412b7a620e7 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial.php @@ -71,7 +71,7 @@ class Financial * 3 365 * 4 European 360 * - * @return int + * @return int|string Result, or a string containing an error */ private static function daysPerYear($year, $basis = 0) { @@ -144,7 +144,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0) { @@ -197,7 +197,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0) { @@ -417,7 +417,7 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); @@ -476,7 +476,7 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); @@ -550,7 +550,7 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); @@ -610,7 +610,7 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); @@ -667,26 +667,22 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); } - $settlement = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true); - $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * 365; + $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); + $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * $daysPerYear; switch ($frequency) { case 1: // annual payments - return ceil($daysBetweenSettlementAndMaturity / 360); case 2: // half-yearly - return ceil($daysBetweenSettlementAndMaturity / 180); case 4: // quarterly - return ceil($daysBetweenSettlementAndMaturity / 90); case 6: // bimonthly - return ceil($daysBetweenSettlementAndMaturity / 60); case 12: // monthly - return ceil($daysBetweenSettlementAndMaturity / 30); + return ceil($daysBetweenSettlementAndMaturity / $daysPerYear * $frequency); } return Functions::VALUE(); @@ -740,7 +736,7 @@ class Financial return Functions::VALUE(); } - if (($settlement > $maturity) || + if (($settlement >= $maturity) || (!self::isValidFrequency($frequency)) || (($basis < 0) || ($basis > 4))) { return Functions::NAN(); @@ -1428,7 +1424,7 @@ class Financial * @param float $finance_rate The interest rate you pay on the money used in the cash flows * @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function MIRR($values, $finance_rate, $reinvestment_rate) { @@ -1470,7 +1466,7 @@ class Financial * @param float $effect_rate Effective interest rate * @param int $npery Number of compounding payments per year * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function NOMINAL($effect_rate = 0, $npery = 0) { @@ -1497,7 +1493,7 @@ class Financial * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0) { @@ -1565,7 +1561,7 @@ class Financial * @param float $pv Present Value * @param float $fv Future Value * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function PDURATION($rate = 0, $pv = 0, $fv = 0) { @@ -1594,7 +1590,7 @@ class Financial * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float + * @return float|string Result, or a string containing an error */ public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) { @@ -1629,7 +1625,7 @@ class Financial * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float + * @return float|string Result, or a string containing an error */ public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { @@ -1713,7 +1709,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return float|string Result, or a string containing an error */ public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis = 0) { @@ -1759,7 +1755,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return float|string Result, or a string containing an error */ public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis = 0) { @@ -1817,7 +1813,7 @@ class Financial * @param float $fv Future Value * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period * - * @return float + * @return float|string Result, or a string containing an error */ public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) { @@ -1933,7 +1929,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return float|string Result, or a string containing an error */ public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis = 0) { @@ -1969,7 +1965,7 @@ class Financial * @param float $pv Present Value * @param float $fv Future Value * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function RRI($nper = 0, $pv = 0, $fv = 0) { @@ -1996,7 +1992,7 @@ class Financial * @param mixed $salvage Value at the end of the depreciation * @param mixed $life Number of periods over which the asset is depreciated * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function SLN($cost, $salvage, $life) { @@ -2026,7 +2022,7 @@ class Financial * @param mixed $life Number of periods over which the asset is depreciated * @param mixed $period Period * - * @return float|string + * @return float|string Result, or a string containing an error */ public static function SYD($cost, $salvage, $life, $period) { @@ -2058,7 +2054,7 @@ class Financial * The maturity date is the date when the Treasury bill expires. * @param int $discount The Treasury bill's discount rate * - * @return float + * @return float|string Result, or a string containing an error */ public static function TBILLEQ($settlement, $maturity, $discount) { @@ -2097,7 +2093,7 @@ class Financial * The maturity date is the date when the Treasury bill expires. * @param int $discount The Treasury bill's discount rate * - * @return float + * @return float|string Result, or a string containing an error */ public static function TBILLPRICE($settlement, $maturity, $discount) { @@ -2152,7 +2148,7 @@ class Financial * The maturity date is the date when the Treasury bill expires. * @param int $price The Treasury bill's price per $100 face value * - * @return float + * @return float|mixed|string */ public static function TBILLYIELD($settlement, $maturity, $price) { @@ -2187,6 +2183,23 @@ class Financial return Functions::VALUE(); } + /** + * XIRR. + * + * Returns the internal rate of return for a schedule of cash flows that is not necessarily periodic. + * + * Excel Function: + * =XIRR(values,dates,guess) + * + * @param float[] $values A series of cash flow payments + * The series of values must contain at least one positive value & one negative value + * @param mixed[] $dates A series of payment dates + * The first payment date indicates the beginning of the schedule of payments + * All other dates must be later than this date, but they may occur in any order + * @param float $guess An optional guess at the expected answer + * + * @return float|mixed|string + */ public static function XIRR($values, $dates, $guess = 0.1) { if ((!is_array($values)) && (!is_array($dates))) { @@ -2199,11 +2212,28 @@ class Financial return Functions::NAN(); } + $datesCount = count($dates); + for ($i = 0; $i < $datesCount; ++$i) { + $dates[$i] = DateTime::getDateValue($dates[$i]); + if (!is_numeric($dates[$i])) { + return Functions::VALUE(); + } + } + if (min($dates) != $dates[0]) { + return Functions::NAN(); + } + // create an initial range, with a root somewhere between 0 and guess $x1 = 0.0; $x2 = $guess; $f1 = self::XNPV($x1, $values, $dates); + if (!is_numeric($f1)) { + return $f1; + } $f2 = self::XNPV($x2, $values, $dates); + if (!is_numeric($f2)) { + return $f2; + } for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { if (($f1 * $f2) < 0.0) { break; @@ -2214,7 +2244,7 @@ class Financial } } if (($f1 * $f2) > 0.0) { - return Functions::VALUE(); + return Functions::NAN(); } $f = self::XNPV($x1, $values, $dates); @@ -2251,15 +2281,15 @@ class Financial * =XNPV(rate,values,dates) * * @param float $rate the discount rate to apply to the cash flows - * @param array of float $values A series of cash flows that corresponds to a schedule of payments in dates. + * @param float[] $values A series of cash flows that corresponds to a schedule of payments in dates. * The first payment is optional and corresponds to a cost or payment that occurs at the beginning of the investment. * If the first value is a cost or payment, it must be a negative value. All succeeding payments are discounted based on a 365-day year. * The series of values must contain at least one positive value and one negative value. - * @param array of mixed $dates A schedule of payment dates that corresponds to the cash flow payments. + * @param mixed[] $dates A schedule of payment dates that corresponds to the cash flow payments. * The first payment date indicates the beginning of the schedule of payments. * All other dates must be later than this date, but they may occur in any order. * - * @return float + * @return float|mixed|string */ public static function XNPV($rate, $values, $dates) { @@ -2277,7 +2307,7 @@ class Financial return Functions::NAN(); } if ((min($values) > 0) || (max($values) < 0)) { - return Functions::VALUE(); + return Functions::NAN(); } $xnpv = 0.0; @@ -2309,7 +2339,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return float|string Result, or a string containing an error */ public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis = 0) { @@ -2360,7 +2390,7 @@ class Financial * 3 Actual/365 * 4 European 30/360 * - * @return float + * @return float|string Result, or a string containing an error */ public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis = 0) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php index 0a607c702ab..1862b008a14 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php @@ -17,8 +17,11 @@ class Functions const COMPATIBILITY_EXCEL = 'Excel'; const COMPATIBILITY_GNUMERIC = 'Gnumeric'; const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc'; + const RETURNDATE_PHP_NUMERIC = 'P'; + const RETURNDATE_UNIX_TIMESTAMP = 'P'; const RETURNDATE_PHP_OBJECT = 'O'; + const RETURNDATE_PHP_DATETIME_OBJECT = 'O'; const RETURNDATE_EXCEL = 'E'; /** @@ -101,16 +104,16 @@ class Functions * * @param string $returnDateType Return Date Format * Permitted values are: - * Functions::RETURNDATE_PHP_NUMERIC 'P' - * Functions::RETURNDATE_PHP_OBJECT 'O' + * Functions::RETURNDATE_UNIX_TIMESTAMP 'P' + * Functions::RETURNDATE_PHP_DATETIME_OBJECT 'O' * Functions::RETURNDATE_EXCEL 'E' * * @return bool Success or failure */ public static function setReturnDateType($returnDateType) { - if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) || - ($returnDateType == self::RETURNDATE_PHP_OBJECT) || + if (($returnDateType == self::RETURNDATE_UNIX_TIMESTAMP) || + ($returnDateType == self::RETURNDATE_PHP_DATETIME_OBJECT) || ($returnDateType == self::RETURNDATE_EXCEL) ) { self::$returnDateType = $returnDateType; @@ -128,8 +131,8 @@ class Functions * * @return string Return Date Format * Possible Return values are: - * Functions::RETURNDATE_PHP_NUMERIC 'P' - * Functions::RETURNDATE_PHP_OBJECT 'O' + * Functions::RETURNDATE_UNIX_TIMESTAMP 'P' + * Functions::RETURNDATE_PHP_DATETIME_OBJECT 'O' * Functions::RETURNDATE_EXCEL 'E' */ public static function getReturnDateType() @@ -267,25 +270,29 @@ class Functions public static function ifCondition($condition) { $condition = self::flattenSingleValue($condition); - if (!isset($condition[0]) && !is_numeric($condition)) { + + if ($condition === '') { $condition = '=""'; } - if (!in_array($condition[0], ['>', '<', '='])) { + + if (!is_string($condition) || !in_array($condition[0], ['>', '<', '='])) { if (!is_numeric($condition)) { $condition = Calculation::wrapResult(strtoupper($condition)); } - return '=' . $condition; + return str_replace('""""', '""', '=' . $condition); } preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches); - list(, $operator, $operand) = $matches; + [, $operator, $operand] = $matches; - if (!is_numeric($operand)) { + if (is_numeric(trim($operand, '"'))) { + $operand = trim($operand, '"'); + } elseif (!is_numeric($operand)) { $operand = str_replace('"', '""', $operand); $operand = Calculation::wrapResult(strtoupper($operand)); } - return $operator . $operand; + return str_replace('""""', '""', $operator . $operand); } /** @@ -639,7 +646,7 @@ class Functions public static function flattenSingleValue($value = '') { while (is_array($value)) { - $value = array_pop($value); + $value = array_shift($value); } return $value; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical.php index 3e6c5e74177..416d119ac8e 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical.php @@ -266,6 +266,10 @@ class Logical */ public static function statementIf($condition = true, $returnIfTrue = 0, $returnIfFalse = false) { + if (Functions::isError($condition)) { + return $condition; + } + $condition = ($condition === null) ? true : (bool) Functions::flattenSingleValue($condition); $returnIfTrue = ($returnIfTrue === null) ? 0 : Functions::flattenSingleValue($returnIfTrue); $returnIfFalse = ($returnIfFalse === null) ? false : Functions::flattenSingleValue($returnIfFalse); @@ -347,4 +351,25 @@ class Logical return self::statementIf(Functions::isError($testValue), $errorpart, $testValue); } + + /** + * IFNA. + * + * Excel Function: + * =IFNA(testValue,napart) + * + * @category Logical Functions + * + * @param mixed $testValue Value to check, is also the value returned when not an NA + * @param mixed $napart Value to return when testValue is an NA condition + * + * @return mixed The value of errorpart or testValue determined by error condition + */ + public static function IFNA($testValue = '', $napart = '') + { + $testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue); + $napart = ($napart === null) ? '' : Functions::flattenSingleValue($napart); + + return self::statementIf(Functions::isNa($testValue), $napart, $testValue); + } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php index e6b0f3203f8..48434300b29 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef.php @@ -98,9 +98,9 @@ class LookupRef return (int) Coordinate::columnIndexFromString($columnKey); } } else { - list($sheet, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true); + [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); if (strpos($cellAddress, ':') !== false) { - list($startAddress, $endAddress) = explode(':', $cellAddress); + [$startAddress, $endAddress] = explode(':', $cellAddress); $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); $returnValue = []; @@ -138,7 +138,7 @@ class LookupRef reset($cellAddress); $isMatrix = (is_numeric(key($cellAddress))); - list($columns, $rows) = Calculation::getMatrixDimensions($cellAddress); + [$columns, $rows] = Calculation::getMatrixDimensions($cellAddress); if ($isMatrix) { return $rows; @@ -175,9 +175,9 @@ class LookupRef } } } else { - list($sheet, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true); + [$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); if (strpos($cellAddress, ':') !== false) { - list($startAddress, $endAddress) = explode(':', $cellAddress); + [$startAddress, $endAddress] = explode(':', $cellAddress); $startAddress = preg_replace('/\D/', '', $startAddress); $endAddress = preg_replace('/\D/', '', $endAddress); $returnValue = []; @@ -187,7 +187,7 @@ class LookupRef return $returnValue; } - list($cellAddress) = explode(':', $cellAddress); + [$cellAddress] = explode(':', $cellAddress); return (int) preg_replace('/\D/', '', $cellAddress); } @@ -215,7 +215,7 @@ class LookupRef reset($cellAddress); $isMatrix = (is_numeric(key($cellAddress))); - list($columns, $rows) = Calculation::getMatrixDimensions($cellAddress); + [$columns, $rows] = Calculation::getMatrixDimensions($cellAddress); if ($isMatrix) { return $columns; @@ -285,7 +285,7 @@ class LookupRef $cellAddress1 = $cellAddress; $cellAddress2 = null; if (strpos($cellAddress, ':') !== false) { - list($cellAddress1, $cellAddress2) = explode(':', $cellAddress); + [$cellAddress1, $cellAddress2] = explode(':', $cellAddress); } if ((!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) || @@ -295,7 +295,7 @@ class LookupRef } if (strpos($cellAddress, '!') !== false) { - list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true); + [$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); $sheetName = trim($sheetName, "'"); $pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); } else { @@ -306,7 +306,7 @@ class LookupRef } if (strpos($cellAddress, '!') !== false) { - list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true); + [$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); $sheetName = trim($sheetName, "'"); $pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); } else { @@ -359,16 +359,16 @@ class LookupRef $sheetName = null; if (strpos($cellAddress, '!')) { - list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true); + [$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); $sheetName = trim($sheetName, "'"); } if (strpos($cellAddress, ':')) { - list($startCell, $endCell) = explode(':', $cellAddress); + [$startCell, $endCell] = explode(':', $cellAddress); } else { $startCell = $endCell = $cellAddress; } - list($startCellColumn, $startCellRow) = Coordinate::coordinateFromString($startCell); - list($endCellColumn, $endCellRow) = Coordinate::coordinateFromString($endCell); + [$startCellColumn, $startCellRow] = Coordinate::coordinateFromString($startCell); + [$endCellColumn, $endCellRow] = Coordinate::coordinateFromString($endCell); $startCellRow += $rows; $startCellColumn = Coordinate::columnIndexFromString($startCellColumn) - 1; @@ -464,9 +464,10 @@ class LookupRef * * @param mixed $lookupValue The value that you want to match in lookup_array * @param mixed $lookupArray The range of cells being searched - * @param mixed $matchType The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. + * @param mixed $matchType The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. + * If match_type is 1 or -1, the list has to be ordered. * - * @return int The relative position of the found item + * @return int|string The relative position of the found item */ public static function MATCH($lookupValue, $lookupArray, $matchType = 1) { @@ -474,9 +475,10 @@ class LookupRef $lookupValue = Functions::flattenSingleValue($lookupValue); $matchType = ($matchType === null) ? 1 : (int) Functions::flattenSingleValue($matchType); - $initialLookupValue = $lookupValue; - // MATCH is not case sensitive - $lookupValue = StringHelper::strToLower($lookupValue); + // MATCH is not case sensitive, so we convert lookup value to be lower cased in case it's string type. + if (is_string($lookupValue)) { + $lookupValue = StringHelper::strToLower($lookupValue); + } // Lookup_value type has to be number, text, or logical values if ((!is_numeric($lookupValue)) && (!is_string($lookupValue)) && (!is_bool($lookupValue))) { @@ -522,16 +524,54 @@ class LookupRef // find the match // ** - if ($matchType == 0 || $matchType == 1) { + if ($matchType === 0 || $matchType === 1) { foreach ($lookupArray as $i => $lookupArrayValue) { - $onlyNumeric = is_numeric($lookupArrayValue) && is_numeric($lookupValue); - $onlyNumericExactMatch = $onlyNumeric && $lookupArrayValue == $lookupValue; - $nonOnlyNumericExactMatch = !$onlyNumeric && $lookupArrayValue === $lookupValue; - $exactMatch = $onlyNumericExactMatch || $nonOnlyNumericExactMatch; - if (($matchType == 0) && $exactMatch) { - // exact match - return $i + 1; - } elseif (($matchType == 1) && ($lookupArrayValue <= $lookupValue)) { + $typeMatch = gettype($lookupValue) === gettype($lookupArrayValue); + $exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue; + $nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue; + $exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch; + + if ($matchType === 0) { + if ($typeMatch && is_string($lookupValue) && (bool) preg_match('/([\?\*])/', $lookupValue)) { + $splitString = $lookupValue; + $chars = array_map(function ($i) use ($splitString) { + return mb_substr($splitString, $i, 1); + }, range(0, mb_strlen($splitString) - 1)); + + $length = count($chars); + $pattern = '/^'; + for ($j = 0; $j < $length; ++$j) { + if ($chars[$j] === '~') { + if (isset($chars[$j + 1])) { + if ($chars[$j + 1] === '*') { + $pattern .= preg_quote($chars[$j + 1], '/'); + ++$j; + } elseif ($chars[$j + 1] === '?') { + $pattern .= preg_quote($chars[$j + 1], '/'); + ++$j; + } + } else { + $pattern .= preg_quote($chars[$j], '/'); + } + } elseif ($chars[$j] === '*') { + $pattern .= '.*'; + } elseif ($chars[$j] === '?') { + $pattern .= '.{1}'; + } else { + $pattern .= preg_quote($chars[$j], '/'); + } + } + + $pattern .= '$/'; + if ((bool) preg_match($pattern, $lookupArrayValue)) { + // exact match + return $i + 1; + } + } elseif ($exactMatch) { + // exact match + return $i + 1; + } + } elseif (($matchType === 1) && $typeMatch && ($lookupArrayValue <= $lookupValue)) { $i = array_search($i, $keySet); // The current value is the (first) match @@ -539,26 +579,26 @@ class LookupRef } } } else { - // matchType = -1 - - // "Special" case: since the array it's supposed to be ordered in descending order, the - // Excel algorithm gives up immediately if the first element is smaller than the searched value - if ($lookupArray[0] < $lookupValue) { - return Functions::NA(); - } - $maxValueKey = null; // The basic algorithm is: // Iterate and keep the highest match until the next element is smaller than the searched value. // Return immediately if perfect match is found foreach ($lookupArray as $i => $lookupArrayValue) { - if ($lookupArrayValue == $lookupValue) { + $typeMatch = gettype($lookupValue) === gettype($lookupArrayValue); + $exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue; + $nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue; + $exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch; + + if ($exactMatch) { // Another "special" case. If a perfect match is found, // the algorithm gives up immediately return $i + 1; - } elseif ($lookupArrayValue >= $lookupValue) { + } elseif ($typeMatch & $lookupArrayValue >= $lookupValue) { $maxValueKey = $i + 1; + } elseif ($typeMatch & $lookupArrayValue < $lookupValue) { + //Excel algorithm gives up immediately if the first element is smaller than the searched value + break; } } @@ -794,8 +834,10 @@ class LookupRef $lookupLower = StringHelper::strToLower($lookup_value); $rowDataLower = StringHelper::strToLower($rowData); - if (($bothNumeric && $rowData > $lookup_value) || - ($bothNotNumeric && $rowDataLower > $lookupLower)) { + if ($not_exact_match && ( + ($bothNumeric && $rowData > $lookup_value) || + ($bothNotNumeric && $rowDataLower > $lookupLower) + )) { break; } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php index a06f3a384c9..f94c8fcc5e2 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig.php @@ -38,6 +38,88 @@ class MathTrig return ($num - ($num % $n)) / $n; } + /** + * ARABIC. + * + * Converts a Roman numeral to an Arabic numeral. + * + * Excel Function: + * ARABIC(text) + * + * @category Mathematical and Trigonometric Functions + * + * @param string $roman + * + * @return int|string the arabic numberal contrived from the roman numeral + */ + public static function ARABIC($roman) + { + // An empty string should return 0 + $roman = substr(trim(strtoupper((string) Functions::flattenSingleValue($roman))), 0, 255); + if ($roman === '') { + return 0; + } + + // Convert the roman numeral to an arabic number + $negativeNumber = $roman[0] === '-'; + if ($negativeNumber) { + $roman = substr($roman, 1); + } + + try { + $arabic = self::calculateArabic(str_split($roman)); + } catch (\Exception $e) { + return Functions::VALUE(); // Invalid character detected + } + + if ($negativeNumber) { + $arabic *= -1; // The number should be negative + } + + return $arabic; + } + + /** + * Recursively calculate the arabic value of a roman numeral. + * + * @param array $roman + * @param int $sum + * @param int $subtract + * + * @return int + */ + protected static function calculateArabic(array $roman, &$sum = 0, $subtract = 0) + { + $lookup = [ + 'M' => 1000, + 'D' => 500, + 'C' => 100, + 'L' => 50, + 'X' => 10, + 'V' => 5, + 'I' => 1, + ]; + + $numeral = array_shift($roman); + if (!isset($lookup[$numeral])) { + throw new \Exception('Invalid character detected'); + } + + $arabic = $lookup[$numeral]; + if (count($roman) > 0 && isset($lookup[$roman[0]]) && $arabic < $lookup[$roman[0]]) { + $subtract += $arabic; + } else { + $sum += ($arabic - $subtract); + $subtract = 0; + } + + if (count($roman) > 0) { + self::calculateArabic($roman, $sum, $subtract); + } + + return $sum; + } + /** * ATAN2. * @@ -59,7 +141,7 @@ class MathTrig * @param float $xCoordinate the x-coordinate of the point * @param float $yCoordinate the y-coordinate of the point * - * @return float the inverse tangent of the specified x- and y-coordinates + * @return float|string the inverse tangent of the specified x- and y-coordinates, or a string containing an error */ public static function ATAN2($xCoordinate = null, $yCoordinate = null) { @@ -84,6 +166,49 @@ class MathTrig return Functions::VALUE(); } + /** + * BASE. + * + * Converts a number into a text representation with the given radix (base). + * + * Excel Function: + * BASE(Number, Radix [Min_length]) + * + * @category Mathematical and Trigonometric Functions + * + * @param float $number + * @param float $radix + * @param int $minLength + * + * @return string the text representation with the given radix (base) + */ + public static function BASE($number, $radix, $minLength = null) + { + $number = Functions::flattenSingleValue($number); + $radix = Functions::flattenSingleValue($radix); + $minLength = Functions::flattenSingleValue($minLength); + + if (is_numeric($number) && is_numeric($radix) && ($minLength === null || is_numeric($minLength))) { + // Truncate to an integer + $number = (int) $number; + $radix = (int) $radix; + $minLength = (int) $minLength; + + if ($number < 0 || $number >= 2 ** 53 || $radix < 2 || $radix > 36) { + return Functions::NAN(); // Numeric range constraints + } + + $outcome = strtoupper((string) base_convert($number, 10, $radix)); + if ($minLength !== null) { + $outcome = str_pad($outcome, $minLength, '0', STR_PAD_LEFT); // String padding + } + + return $outcome; + } + + return Functions::VALUE(); + } + /** * CEILING. * @@ -100,7 +225,7 @@ class MathTrig * @param float $number the number you want to round * @param float $significance the multiple to which you want to round * - * @return float Rounded Number + * @return float|string Rounded Number, or a string containing an error */ public static function CEILING($number, $significance = null) { @@ -139,7 +264,7 @@ class MathTrig * @param int $numObjs Number of different objects * @param int $numInSet Number of objects in each combination * - * @return int Number of combinations + * @return int|string Number of combinations, or a string containing an error */ public static function COMBIN($numObjs, $numInSet) { @@ -175,7 +300,7 @@ class MathTrig * * @param float $number Number to round * - * @return int Rounded Number + * @return int|string Rounded Number, or a string containing an error */ public static function EVEN($number) { @@ -209,7 +334,7 @@ class MathTrig * * @param float $factVal Factorial Value * - * @return int Factorial + * @return int|string Factorial, or a string containing an error */ public static function FACT($factVal) { @@ -220,10 +345,9 @@ class MathTrig return Functions::NAN(); } $factLoop = floor($factVal); - if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { - if ($factVal > $factLoop) { - return Functions::NAN(); - } + if ((Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) && + ($factVal > $factLoop)) { + return Functions::NAN(); } $factorial = 1; @@ -249,7 +373,7 @@ class MathTrig * * @param float $factVal Factorial Value * - * @return int Double Factorial + * @return int|string Double Factorial, or a string containing an error */ public static function FACTDOUBLE($factVal) { @@ -285,7 +409,7 @@ class MathTrig * @param float $number Number to round * @param float $significance Significance * - * @return float Rounded Number + * @return float|string Rounded Number, or a string containing an error */ public static function FLOOR($number, $significance = null) { @@ -302,7 +426,9 @@ class MathTrig return Functions::DIV0(); } elseif ($number == 0.0) { return 0.0; - } elseif (self::SIGN($number) == self::SIGN($significance)) { + } elseif (self::SIGN($significance) == 1) { + return floor($number / $significance) * $significance; + } elseif (self::SIGN($number) == -1 && self::SIGN($significance) == -1) { return floor($number / $significance) * $significance; } @@ -312,6 +438,80 @@ class MathTrig return Functions::VALUE(); } + /** + * FLOOR.MATH. + * + * Round a number down to the nearest integer or to the nearest multiple of significance. + * + * Excel Function: + * FLOOR.MATH(number[,significance[,mode]]) + * + * @category Mathematical and Trigonometric Functions + * + * @param float $number Number to round + * @param float $significance Significance + * @param int $mode direction to round negative numbers + * + * @return float|string Rounded Number, or a string containing an error + */ + public static function FLOORMATH($number, $significance = null, $mode = 0) + { + $number = Functions::flattenSingleValue($number); + $significance = Functions::flattenSingleValue($significance); + $mode = Functions::flattenSingleValue($mode); + + if (is_numeric($number) && $significance === null) { + $significance = $number / abs($number); + } + + if (is_numeric($number) && is_numeric($significance) && is_numeric($mode)) { + if ($significance == 0.0) { + return Functions::DIV0(); + } elseif ($number == 0.0) { + return 0.0; + } elseif (self::SIGN($significance) == -1 || (self::SIGN($number) == -1 && !empty($mode))) { + return ceil($number / $significance) * $significance; + } + + return floor($number / $significance) * $significance; + } + + return Functions::VALUE(); + } + + /** + * FLOOR.PRECISE. + * + * Rounds number down, toward zero, to the nearest multiple of significance. + * + * Excel Function: + * FLOOR.PRECISE(number[,significance]) + * + * @category Mathematical and Trigonometric Functions + * + * @param float $number Number to round + * @param float $significance Significance + * + * @return float|string Rounded Number, or a string containing an error + */ + public static function FLOORPRECISE($number, $significance = 1) + { + $number = Functions::flattenSingleValue($number); + $significance = Functions::flattenSingleValue($significance); + + if ((is_numeric($number)) && (is_numeric($significance))) { + if ($significance == 0.0) { + return Functions::DIV0(); + } elseif ($number == 0.0) { + return 0.0; + } + + return floor($number / abs($significance)) * abs($significance); + } + + return Functions::VALUE(); + } + private static function evaluateGCD($a, $b) { return $b ? self::evaluateGCD($b, $a % $b) : $a; @@ -331,7 +531,7 @@ class MathTrig * * @param mixed ...$args Data values * - * @return int Greatest Common Divisor + * @return int|mixed|string Greatest Common Divisor, or a string containing an error */ public static function GCD(...$args) { @@ -365,7 +565,7 @@ class MathTrig * * @param float $number Number to cast to an integer * - * @return int Integer value + * @return int|string Integer value, or a string containing an error */ public static function INT($number) { @@ -398,7 +598,7 @@ class MathTrig * * @param mixed ...$args Data values * - * @return int Lowest Common Multiplier + * @return int|string Lowest Common Multiplier, or a string containing an error */ public static function LCM(...$args) { @@ -450,7 +650,7 @@ class MathTrig * @param float $number The positive real number for which you want the logarithm * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10. * - * @return float + * @return float|string The result, or a string containing an error */ public static function logBase($number = null, $base = 10) { @@ -479,7 +679,7 @@ class MathTrig * * @param array $matrixValues A matrix of values * - * @return float + * @return float|string The result, or a string containing an error */ public static function MDETERM($matrixValues) { @@ -531,7 +731,7 @@ class MathTrig * * @param array $matrixValues A matrix of values * - * @return array + * @return array|string The result, or a string containing an error */ public static function MINVERSE($matrixValues) { @@ -581,7 +781,7 @@ class MathTrig * @param array $matrixData1 A matrix of values * @param array $matrixData2 A matrix of values * - * @return array + * @return array|string The result, or a string containing an error */ public static function MMULT($matrixData1, $matrixData2) { @@ -643,7 +843,7 @@ class MathTrig * @param int $a Dividend * @param int $b Divisor * - * @return int Remainder + * @return int|string Remainder, or a string containing an error */ public static function MOD($a = 1, $b = 1) { @@ -669,7 +869,7 @@ class MathTrig * @param float $number Number to round * @param int $multiple Multiple to which you want to round $number * - * @return float Rounded Number + * @return float|string Rounded Number, or a string containing an error */ public static function MROUND($number, $multiple) { @@ -699,7 +899,7 @@ class MathTrig * * @param array of mixed Data Series * - * @return float + * @return float|string The result, or a string containing an error */ public static function MULTINOMIAL(...$args) { @@ -736,7 +936,7 @@ class MathTrig * * @param float $number Number to round * - * @return int Rounded Number + * @return int|string Rounded Number, or a string containing an error */ public static function ODD($number) { @@ -771,7 +971,7 @@ class MathTrig * @param float $x * @param float $y * - * @return float + * @return float|string The result, or a string containing an error */ public static function POWER($x = 0, $y = 2) { @@ -930,7 +1130,7 @@ class MathTrig * @param float $number Number to round * @param int $digits Number of digits to which you want to round $number * - * @return float Rounded Number + * @return float|string Rounded Number, or a string containing an error */ public static function ROUNDUP($number, $digits) { @@ -938,12 +1138,11 @@ class MathTrig $digits = Functions::flattenSingleValue($digits); if ((is_numeric($number)) && (is_numeric($digits))) { - $significance = pow(10, (int) $digits); if ($number < 0.0) { - return floor($number * $significance) / $significance; + return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN); } - return ceil($number * $significance) / $significance; + return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN); } return Functions::VALUE(); @@ -957,7 +1156,7 @@ class MathTrig * @param float $number Number to round * @param int $digits Number of digits to which you want to round $number * - * @return float Rounded Number + * @return float|string Rounded Number, or a string containing an error */ public static function ROUNDDOWN($number, $digits) { @@ -965,12 +1164,11 @@ class MathTrig $digits = Functions::flattenSingleValue($digits); if ((is_numeric($number)) && (is_numeric($digits))) { - $significance = pow(10, (int) $digits); if ($number < 0.0) { - return ceil($number * $significance) / $significance; + return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP); } - return floor($number * $significance) / $significance; + return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP); } return Functions::VALUE(); @@ -986,7 +1184,7 @@ class MathTrig * @param float $m Step by which to increase $n for each term in the series * @param array of mixed Data Series * - * @return float + * @return float|string The result, or a string containing an error */ public static function SERIESSUM(...$args) { @@ -1025,7 +1223,7 @@ class MathTrig * * @param float $number Number to round * - * @return int sign value + * @return int|string sign value, or a string containing an error */ public static function SIGN($number) { @@ -1052,7 +1250,7 @@ class MathTrig * * @param float $number Number * - * @return float Square Root of Number * Pi + * @return float|string Square Root of Number * Pi, or a string containing an error */ public static function SQRTPI($number) { @@ -1074,7 +1272,7 @@ class MathTrig return array_filter( $args, function ($index) use ($cellReference) { - list(, $row, $column) = explode('.', $index); + [, $row, $column] = explode('.', $index); return $cellReference->getWorksheet()->getRowDimension($row)->getVisible() && $cellReference->getWorksheet()->getColumnDimension($column)->getVisible(); @@ -1088,7 +1286,7 @@ class MathTrig return array_filter( $args, function ($index) use ($cellReference) { - list(, $row, $column) = explode('.', $index); + [, $row, $column] = explode('.', $index); if ($cellReference->getWorksheet()->cellExists($column . $row)) { //take this cell out if it contains the SUBTOTAL or AGGREGATE functions in a formula $isFormula = $cellReference->getWorksheet()->getCell($column . $row)->isFormula(); @@ -1116,7 +1314,7 @@ class MathTrig * in hidden rows or columns * @param array of mixed Data Series * - * @return float + * @return float|string */ public static function SUBTOTAL(...$args) { @@ -1306,7 +1504,7 @@ class MathTrig * * @param mixed ...$args Data values * - * @return float + * @return float|string The result, or a string containing an error */ public static function SUMPRODUCT(...$args) { @@ -1451,7 +1649,7 @@ class MathTrig * @param float $value * @param int $digits * - * @return float Truncated value + * @return float|string Truncated value, or a string containing an error */ public static function TRUNC($value = 0, $digits = 0) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php index 395b46ae7ca..b1c7fb020ef 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical.php @@ -518,6 +518,44 @@ class Statistical return Functions::NULL(); } + /** + * MS Excel does not count Booleans if passed as cell values, but they are counted if passed as literals. + * OpenOffice Calc always counts Booleans. + * Gnumeric never counts Booleans. + * + * @param mixed $arg + * @param mixed $k + * + * @return int|mixed + */ + private static function testAcceptedBoolean($arg, $k) + { + if ((is_bool($arg)) && + ((!Functions::isCellValue($k) && (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_EXCEL)) || + (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (int) $arg; + } + + return $arg; + } + + /** + * @param mixed $arg + * @param mixed $k + * + * @return bool + */ + private static function isAcceptedCountable($arg, $k) + { + if (((is_numeric($arg)) && (!is_string($arg))) || + ((is_numeric($arg)) && (!Functions::isCellValue($k)) && + (Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_GNUMERIC))) { + return true; + } + + return false; + } + /** * AVEDEV. * @@ -531,43 +569,43 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function AVEDEV(...$args) { $aArgs = Functions::flattenArrayIndexed($args); // Return value - $returnValue = null; + $returnValue = 0; - $aMean = self::AVERAGE($aArgs); - if ($aMean != Functions::DIV0()) { - $aCount = 0; - foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) { - $arg = (int) $arg; - } - // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if ($returnValue === null) { - $returnValue = abs($arg - $aMean); - } else { - $returnValue += abs($arg - $aMean); - } - ++$aCount; - } - } - - // Return - if ($aCount == 0) { - return Functions::DIV0(); - } - - return $returnValue / $aCount; + $aMean = self::AVERAGE(...$args); + if ($aMean === Functions::DIV0()) { + return Functions::NAN(); + } elseif ($aMean === Functions::VALUE()) { + return Functions::VALUE(); } - return Functions::NAN(); + $aCount = 0; + foreach ($aArgs as $k => $arg) { + $arg = self::testAcceptedBoolean($arg, $k); + // Is it a numeric value? + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { + return Functions::VALUE(); + } + if (self::isAcceptedCountable($arg, $k)) { + $returnValue += abs($arg - $aMean); + ++$aCount; + } + } + + // Return + if ($aCount === 0) { + return Functions::DIV0(); + } + + return $returnValue / $aCount; } /** @@ -582,7 +620,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function AVERAGE(...$args) { @@ -590,17 +628,15 @@ class Statistical // Loop through arguments foreach (Functions::flattenArrayIndexed($args) as $k => $arg) { - if ((is_bool($arg)) && - ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) { - $arg = (int) $arg; - } + $arg = self::testAcceptedBoolean($arg, $k); // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { - if ($returnValue === null) { - $returnValue = $arg; - } else { - $returnValue += $arg; - } + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if ((is_string($arg)) && (!is_numeric($arg)) && (!Functions::isCellValue($k))) { + return Functions::VALUE(); + } + if (self::isAcceptedCountable($arg, $k)) { + $returnValue += $arg; ++$aCount; } } @@ -625,7 +661,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function AVERAGEA(...$args) { @@ -643,11 +679,7 @@ class Statistical } elseif (is_string($arg)) { $arg = 0; } - if ($returnValue === null) { - $returnValue = $arg; - } else { - $returnValue += $arg; - } + $returnValue += $arg; ++$aCount; } } @@ -674,7 +706,7 @@ class Statistical * @param string $condition the criteria that defines which cells will be checked * @param mixed[] $averageArgs Data values * - * @return float + * @return float|string */ public static function AVERAGEIF($aArgs, $condition, $averageArgs = []) { @@ -686,18 +718,23 @@ class Statistical $averageArgs = $aArgs; } $condition = Functions::ifCondition($condition); + $conditionIsNumeric = strpos($condition, '"') === false; + // Loop through arguments $aCount = 0; foreach ($aArgs as $key => $arg) { if (!is_numeric($arg)) { + if ($conditionIsNumeric) { + continue; + } $arg = Calculation::wrapResult(strtoupper($arg)); + } elseif (!$conditionIsNumeric) { + continue; } $testCondition = '=' . $arg . $condition; if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if (($returnValue === null) || ($arg > $returnValue)) { - $returnValue += $arg; - ++$aCount; - } + $returnValue += $averageArgs[$key]; + ++$aCount; } } @@ -719,7 +756,7 @@ class Statistical * @param mixed $rMin * @param mixed $rMax * - * @return float + * @return float|string */ public static function BETADIST($value, $alpha, $beta, $rMin = 0, $rMax = 1) { @@ -758,7 +795,7 @@ class Statistical * @param float $rMin Minimum value * @param float $rMax Maximum value * - * @return float + * @return float|string */ public static function BETAINV($probability, $alpha, $beta, $rMin = 0, $rMax = 1) { @@ -816,17 +853,17 @@ class Statistical * @param float $probability Probability of success on each trial * @param bool $cumulative * - * @return float - * - * @todo Cumulative distribution function + * @return float|string */ public static function BINOMDIST($value, $trials, $probability, $cumulative) { - $value = floor(Functions::flattenSingleValue($value)); - $trials = floor(Functions::flattenSingleValue($trials)); + $value = Functions::flattenSingleValue($value); + $trials = Functions::flattenSingleValue($trials); $probability = Functions::flattenSingleValue($probability); if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) { + $value = floor($value); + $trials = floor($trials); if (($value < 0) || ($value > $trials)) { return Functions::NAN(); } @@ -858,14 +895,15 @@ class Statistical * @param float $value Value for the function * @param float $degrees degrees of freedom * - * @return float + * @return float|string */ public static function CHIDIST($value, $degrees) { $value = Functions::flattenSingleValue($value); - $degrees = floor(Functions::flattenSingleValue($degrees)); + $degrees = Functions::flattenSingleValue($degrees); if ((is_numeric($value)) && (is_numeric($degrees))) { + $degrees = floor($degrees); if ($degrees < 1) { return Functions::NAN(); } @@ -891,14 +929,16 @@ class Statistical * @param float $probability Probability for the function * @param float $degrees degrees of freedom * - * @return float + * @return float|string */ public static function CHIINV($probability, $degrees) { $probability = Functions::flattenSingleValue($probability); - $degrees = floor(Functions::flattenSingleValue($degrees)); + $degrees = Functions::flattenSingleValue($degrees); if ((is_numeric($probability)) && (is_numeric($degrees))) { + $degrees = floor($degrees); + $xLo = 100; $xHi = 0; @@ -908,7 +948,7 @@ class Statistical while ((abs($dx) > Functions::PRECISION) && ($i++ < self::MAX_ITERATIONS)) { // Apply Newton-Raphson step - $result = self::CHIDIST($x, $degrees); + $result = 1 - (self::incompleteGamma($degrees / 2, $x / 2) / self::gamma($degrees / 2)); $error = $result - $probability; if ($error == 0.0) { $dx = 0; @@ -950,15 +990,16 @@ class Statistical * @param float $stdDev Standard Deviation * @param float $size * - * @return float + * @return float|string */ public static function CONFIDENCE($alpha, $stdDev, $size) { $alpha = Functions::flattenSingleValue($alpha); $stdDev = Functions::flattenSingleValue($stdDev); - $size = floor(Functions::flattenSingleValue($size)); + $size = Functions::flattenSingleValue($size); if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) { + $size = floor($size); if (($alpha <= 0) || ($alpha >= 1)) { return Functions::NAN(); } @@ -980,7 +1021,7 @@ class Statistical * @param mixed $yValues array of mixed Data Series Y * @param null|mixed $xValues array of mixed Data Series X * - * @return float + * @return float|string */ public static function CORREL($yValues, $xValues = null) { @@ -1025,12 +1066,11 @@ class Statistical // Loop through arguments $aArgs = Functions::flattenArrayIndexed($args); foreach ($aArgs as $k => $arg) { - if ((is_bool($arg)) && - ((!Functions::isCellValue($k)) || (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))) { - $arg = (int) $arg; - } + $arg = self::testAcceptedBoolean($arg, $k); // Is it a numeric value? - if ((is_numeric($arg)) && (!is_string($arg))) { + // Strings containing numeric values are only counted if they are string literals (not cell values) + // and then only in MS Excel and in Open Office, not in Gnumeric + if (self::isAcceptedCountable($arg, $k)) { ++$returnValue; } } @@ -1057,10 +1097,10 @@ class Statistical $returnValue = 0; // Loop through arguments - $aArgs = Functions::flattenArray($args); - foreach ($aArgs as $arg) { - // Is it a numeric, boolean or string value? - if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + $aArgs = Functions::flattenArrayIndexed($args); + foreach ($aArgs as $k => $arg) { + // Nulls are counted if literals, but not if cell values + if ($arg !== null || (!Functions::isCellValue($k))) { ++$returnValue; } } @@ -1119,10 +1159,16 @@ class Statistical $aArgs = Functions::flattenArray($aArgs); $condition = Functions::ifCondition($condition); + $conditionIsNumeric = strpos($condition, '"') === false; // Loop through arguments foreach ($aArgs as $arg) { if (!is_numeric($arg)) { + if ($conditionIsNumeric) { + continue; + } $arg = Calculation::wrapResult(strtoupper($arg)); + } elseif (!$conditionIsNumeric) { + continue; } $testCondition = '=' . $arg . $condition; if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { @@ -1134,6 +1180,78 @@ class Statistical return $returnValue; } + /** + * COUNTIFS. + * + * Counts the number of cells that contain numbers within the list of arguments + * + * Excel Function: + * COUNTIFS(criteria_range1, criteria1, [criteria_range2, criteria2]…) + * + * @category Statistical Functions + * + * @param mixed $args Criterias + * + * @return int + */ + public static function COUNTIFS(...$args) + { + $arrayList = $args; + + // Return value + $returnValue = 0; + + if (empty($arrayList)) { + return $returnValue; + } + + $aArgsArray = []; + $conditions = []; + + while (count($arrayList) > 0) { + $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); + $conditions[] = Functions::ifCondition(array_shift($arrayList)); + } + + // Loop through each arg and see if arguments and conditions are true + foreach (array_keys($aArgsArray[0]) as $index) { + $valid = true; + + foreach ($conditions as $cidx => $condition) { + $conditionIsNumeric = strpos($condition, '"') === false; + $arg = $aArgsArray[$cidx][$index]; + + // Loop through arguments + if (!is_numeric($arg)) { + if ($conditionIsNumeric) { + $valid = false; + + break; // if false found, don't need to check other conditions + } + $arg = Calculation::wrapResult(strtoupper($arg)); + } elseif (!$conditionIsNumeric) { + $valid = false; + + break; // if false found, don't need to check other conditions + } + $testCondition = '=' . $arg . $condition; + if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + // Is not a value within our criteria + $valid = false; + + break; // if false found, don't need to check other conditions + } + } + + if ($valid) { + ++$returnValue; + } + } + + // Return + return $returnValue; + } + /** * COVAR. * @@ -1142,7 +1260,7 @@ class Statistical * @param mixed $yValues array of mixed Data Series Y * @param mixed $xValues array of mixed Data Series X * - * @return float + * @return float|string */ public static function COVAR($yValues, $xValues) { @@ -1175,7 +1293,7 @@ class Statistical * @param float $probability probability of a success on each trial * @param float $alpha criterion value * - * @return int + * @return int|string * * @todo Warning. This implementation differs from the algorithm detailed on the MS * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess @@ -1189,19 +1307,23 @@ class Statistical $alpha = Functions::flattenSingleValue($alpha); if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) { + $trials = (int) $trials; if ($trials < 0) { return Functions::NAN(); - } elseif (($probability < 0) || ($probability > 1)) { + } elseif (($probability < 0.0) || ($probability > 1.0)) { return Functions::NAN(); - } elseif (($alpha < 0) || ($alpha > 1)) { + } elseif (($alpha < 0.0) || ($alpha > 1.0)) { return Functions::NAN(); - } elseif ($alpha <= 0.5) { + } + + if ($alpha <= 0.5) { $t = sqrt(log(1 / ($alpha * $alpha))); $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t)); } else { $t = sqrt(log(1 / pow(1 - $alpha, 2))); $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t); } + $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability))); if ($Guess < 0) { $Guess = 0; @@ -1298,7 +1420,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function DEVSQ(...$args) { @@ -1349,7 +1471,7 @@ class Statistical * @param float $lambda The parameter value * @param bool $cumulative * - * @return float + * @return float|string */ public static function EXPONDIST($value, $lambda, $cumulative) { @@ -1382,7 +1504,7 @@ class Statistical * * @param float $value * - * @return float + * @return float|string */ public static function FISHER($value) { @@ -1408,7 +1530,7 @@ class Statistical * * @param float $value * - * @return float + * @return float|string */ public static function FISHERINV($value) { @@ -1430,7 +1552,7 @@ class Statistical * @param mixed $yValues array of mixed Data Series Y * @param mixed $xValues of mixed Data Series X * - * @return float + * @return bool|float|string */ public static function FORECAST($xValue, $yValues, $xValues) { @@ -1464,7 +1586,7 @@ class Statistical * @param float $b Parameter to the distribution * @param bool $cumulative * - * @return float + * @return float|string */ public static function GAMMADIST($value, $a, $b, $cumulative) { @@ -1497,7 +1619,7 @@ class Statistical * @param float $alpha Parameter to the distribution * @param float $beta Parameter to the distribution * - * @return float + * @return float|string */ public static function GAMMAINV($probability, $alpha, $beta) { @@ -1558,7 +1680,7 @@ class Statistical * * @param float $value * - * @return float + * @return float|string */ public static function GAMMALN($value) { @@ -1589,7 +1711,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function GEOMEAN(...$args) { @@ -1609,7 +1731,7 @@ class Statistical /** * GROWTH. * - * Returns values along a predicted emponential Trend + * Returns values along a predicted exponential Trend * * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X @@ -1651,12 +1773,12 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function HARMEAN(...$args) { // Return value - $returnValue = Functions::NA(); + $returnValue = 0; // Loop through arguments $aArgs = Functions::flattenArray($args); @@ -1670,11 +1792,7 @@ class Statistical if ($arg <= 0) { return Functions::NAN(); } - if ($returnValue === null) { - $returnValue = (1 / $arg); - } else { - $returnValue += (1 / $arg); - } + $returnValue += (1 / $arg); ++$aCount; } } @@ -1684,7 +1802,7 @@ class Statistical return 1 / ($returnValue / $aCount); } - return $returnValue; + return Functions::NA(); } /** @@ -1698,7 +1816,7 @@ class Statistical * @param float $populationSuccesses Number of successes in the population * @param float $populationNumber Population size * - * @return float + * @return float|string */ public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber) { @@ -1734,7 +1852,7 @@ class Statistical * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float + * @return float|string */ public static function INTERCEPT($yValues, $xValues) { @@ -1765,7 +1883,7 @@ class Statistical * * @param array ...$args Data Series * - * @return float + * @return float|string */ public static function KURT(...$args) { @@ -1811,7 +1929,7 @@ class Statistical * @param mixed $args Data values * @param int $entry Position (ordered from the largest) in the array or range of data to return * - * @return float + * @return float|string The result, or a string containing an error */ public static function LARGE(...$args) { @@ -1852,7 +1970,7 @@ class Statistical * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return array + * @return array|int|string The result, or a string containing an error */ public static function LINEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -1911,7 +2029,7 @@ class Statistical * @param bool $const a logical value specifying whether to force the intersect to equal 0 * @param bool $stats a logical value specifying whether to return additional regression statistics * - * @return array + * @return array|int|string The result, or a string containing an error */ public static function LOGEST($yValues, $xValues = null, $const = true, $stats = false) { @@ -1974,7 +2092,7 @@ class Statistical * @param float $mean * @param float $stdDev * - * @return float + * @return float|string The result, or a string containing an error * * @todo Try implementing P J Acklam's refinement algorithm for greater * accuracy if I can get my head round the mathematics @@ -2007,7 +2125,7 @@ class Statistical * @param float $mean * @param float $stdDev * - * @return float + * @return float|string The result, or a string containing an error */ public static function LOGNORMDIST($value, $mean, $stdDev) { @@ -2105,44 +2223,61 @@ class Statistical } /** - * MAXIF. + * MAXIFS. * * Counts the maximum value within a range of cells that contain numbers within the list of arguments * * Excel Function: - * MAXIF(value1[,value2[, ...]],condition) + * MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) * - * @category Mathematical and Trigonometric Functions + * @category Statistical Functions * - * @param mixed $aArgs Data values - * @param string $condition the criteria that defines which cells will be checked - * @param mixed $sumArgs + * @param mixed $args Data range and criterias * * @return float */ - public static function MAXIF($aArgs, $condition, $sumArgs = []) + public static function MAXIFS(...$args) { + $arrayList = $args; + + // Return value $returnValue = null; - $aArgs = Functions::flattenArray($aArgs); - $sumArgs = Functions::flattenArray($sumArgs); - if (empty($sumArgs)) { - $sumArgs = $aArgs; + $maxArgs = Functions::flattenArray(array_shift($arrayList)); + $aArgsArray = []; + $conditions = []; + + while (count($arrayList) > 0) { + $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); + $conditions[] = Functions::ifCondition(array_shift($arrayList)); } - $condition = Functions::ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { - $arg = Calculation::wrapResult(strtoupper($arg)); - } - $testCondition = '=' . $arg . $condition; - if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if (($returnValue === null) || ($arg > $returnValue)) { - $returnValue = $arg; + + // Loop through each arg and see if arguments and conditions are true + foreach ($maxArgs as $index => $value) { + $valid = true; + + foreach ($conditions as $cidx => $condition) { + $arg = $aArgsArray[$cidx][$index]; + + // Loop through arguments + if (!is_numeric($arg)) { + $arg = Calculation::wrapResult(strtoupper($arg)); } + $testCondition = '=' . $arg . $condition; + if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + // Is not a value within our criteria + $valid = false; + + break; // if false found, don't need to check other conditions + } + } + + if ($valid) { + $returnValue = $returnValue === null ? $value : max($value, $returnValue); } } + // Return return $returnValue; } @@ -2158,7 +2293,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string The result, or a string containing an error */ public static function MEDIAN(...$args) { @@ -2268,44 +2403,61 @@ class Statistical } /** - * MINIF. + * MINIFS. * * Returns the minimum value within a range of cells that contain numbers within the list of arguments * * Excel Function: - * MINIF(value1[,value2[, ...]],condition) + * MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) * - * @category Mathematical and Trigonometric Functions + * @category Statistical Functions * - * @param mixed $aArgs Data values - * @param string $condition the criteria that defines which cells will be checked - * @param mixed $sumArgs + * @param mixed $args Data range and criterias * * @return float */ - public static function MINIF($aArgs, $condition, $sumArgs = []) + public static function MINIFS(...$args) { + $arrayList = $args; + + // Return value $returnValue = null; - $aArgs = Functions::flattenArray($aArgs); - $sumArgs = Functions::flattenArray($sumArgs); - if (empty($sumArgs)) { - $sumArgs = $aArgs; + $minArgs = Functions::flattenArray(array_shift($arrayList)); + $aArgsArray = []; + $conditions = []; + + while (count($arrayList) > 0) { + $aArgsArray[] = Functions::flattenArray(array_shift($arrayList)); + $conditions[] = Functions::ifCondition(array_shift($arrayList)); } - $condition = Functions::ifCondition($condition); - // Loop through arguments - foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { - $arg = Calculation::wrapResult(strtoupper($arg)); - } - $testCondition = '=' . $arg . $condition; - if (Calculation::getInstance()->_calculateFormulaValue($testCondition)) { - if (($returnValue === null) || ($arg < $returnValue)) { - $returnValue = $arg; + + // Loop through each arg and see if arguments and conditions are true + foreach ($minArgs as $index => $value) { + $valid = true; + + foreach ($conditions as $cidx => $condition) { + $arg = $aArgsArray[$cidx][$index]; + + // Loop through arguments + if (!is_numeric($arg)) { + $arg = Calculation::wrapResult(strtoupper($arg)); } + $testCondition = '=' . $arg . $condition; + if (!Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + // Is not a value within our criteria + $valid = false; + + break; // if false found, don't need to check other conditions + } + } + + if ($valid) { + $returnValue = $returnValue === null ? $value : min($value, $returnValue); } } + // Return return $returnValue; } @@ -2359,7 +2511,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string The result, or a string containing an error */ public static function MODE(...$args) { @@ -2396,7 +2548,7 @@ class Statistical * @param float $successes Threshold number of Successes * @param float $probability Probability of success on each trial * - * @return float + * @return float|string The result, or a string containing an error */ public static function NEGBINOMDIST($failures, $successes, $probability) { @@ -2434,7 +2586,7 @@ class Statistical * @param float $stdDev Standard Deviation * @param bool $cumulative * - * @return float + * @return float|string The result, or a string containing an error */ public static function NORMDIST($value, $mean, $stdDev, $cumulative) { @@ -2467,7 +2619,7 @@ class Statistical * @param float $mean Mean Value * @param float $stdDev Standard Deviation * - * @return float + * @return float|string The result, or a string containing an error */ public static function NORMINV($probability, $mean, $stdDev) { @@ -2498,7 +2650,7 @@ class Statistical * * @param float $value * - * @return float + * @return float|string The result, or a string containing an error */ public static function NORMSDIST($value) { @@ -2514,7 +2666,7 @@ class Statistical * * @param float $value * - * @return float + * @return float|string The result, or a string containing an error */ public static function NORMSINV($value) { @@ -2534,7 +2686,7 @@ class Statistical * @param mixed $args Data values * @param float $entry Percentile value in the range 0..1, inclusive. * - * @return float + * @return float|string The result, or a string containing an error */ public static function PERCENTILE(...$args) { @@ -2632,7 +2784,7 @@ class Statistical * @param int $numObjs Number of different objects * @param int $numInSet Number of objects in each permutation * - * @return int Number of permutations + * @return int|string Number of permutations, or a string containing an error */ public static function PERMUT($numObjs, $numInSet) { @@ -2662,7 +2814,7 @@ class Statistical * @param float $mean Mean Value * @param bool $cumulative * - * @return float + * @return float|string The result, or a string containing an error */ public static function POISSON($value, $mean, $cumulative) { @@ -2704,7 +2856,7 @@ class Statistical * @param mixed $args Data values * @param int $entry Quartile value in the range 1..3, inclusive. * - * @return float + * @return float|string The result, or a string containing an error */ public static function QUARTILE(...$args) { @@ -2734,7 +2886,7 @@ class Statistical * @param float[] $valueSet An array of, or a reference to, a list of numbers * @param int $order Order to sort the values in the value set * - * @return float + * @return float|string The result, or a string containing an error */ public static function RANK($value, $valueSet, $order = 0) { @@ -2769,7 +2921,7 @@ class Statistical * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float + * @return float|string The result, or a string containing an error */ public static function RSQ($yValues, $xValues) { @@ -2800,7 +2952,7 @@ class Statistical * * @param array ...$args Data Series * - * @return float + * @return float|string The result, or a string containing an error */ public static function SKEW(...$args) { @@ -2837,7 +2989,7 @@ class Statistical * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float + * @return float|string The result, or a string containing an error */ public static function SLOPE($yValues, $xValues) { @@ -2872,7 +3024,7 @@ class Statistical * @param mixed $args Data values * @param int $entry Position (ordered from the smallest) in the array or range of data to return * - * @return float + * @return float|string The result, or a string containing an error */ public static function SMALL(...$args) { @@ -2911,7 +3063,7 @@ class Statistical * @param float $mean Mean Value * @param float $stdDev Standard Deviation * - * @return float Standardized value + * @return float|string Standardized value, or a string containing an error */ public static function STANDARDIZE($value, $mean, $stdDev) { @@ -2943,7 +3095,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string The result, or a string containing an error */ public static function STDEV(...$args) { @@ -2992,7 +3144,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function STDEVA(...$args) { @@ -3044,7 +3196,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function STDEVP(...$args) { @@ -3091,7 +3243,7 @@ class Statistical * * @param mixed ...$args Data values * - * @return float + * @return float|string */ public static function STDEVPA(...$args) { @@ -3139,7 +3291,7 @@ class Statistical * @param mixed[] $yValues Data Series Y * @param mixed[] $xValues Data Series X * - * @return float + * @return float|string */ public static function STEYX($yValues, $xValues) { @@ -3169,7 +3321,7 @@ class Statistical * @param float $degrees degrees of freedom * @param float $tails number of tails (1 or 2) * - * @return float + * @return float|string The result, or a string containing an error */ public static function TDIST($value, $degrees, $tails) { @@ -3233,7 +3385,7 @@ class Statistical * @param float $probability Probability for the function * @param float $degrees degrees of freedom * - * @return float + * @return float|string The result, or a string containing an error */ public static function TINV($probability, $degrees) { @@ -3330,7 +3482,7 @@ class Statistical * @param mixed $args Data values * @param float $discard Percentage to discard * - * @return float + * @return float|string */ public static function TRIMMEAN(...$args) { @@ -3603,7 +3755,7 @@ class Statistical * @param float $m0 Alpha Parameter * @param float $sigma Beta Parameter * - * @return float + * @return float|string */ public static function ZTEST($dataSet, $m0, $sigma = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php index e30b2ff7e89..bbb03926ca4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData.php @@ -52,7 +52,7 @@ class TextData return ($stringValue) ? Calculation::getTRUE() : Calculation::getFALSE(); } - if (self::$invalidChars == null) { + if (self::$invalidChars === null) { self::$invalidChars = range(chr(0), chr(31)); } @@ -84,6 +84,15 @@ class TextData return null; } + private static function convertBooleanValue($value) + { + if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { + return (int) $value; + } + + return ($value) ? Calculation::getTRUE() : Calculation::getFALSE(); + } + /** * ASCIICODE. * @@ -98,11 +107,7 @@ class TextData } $characters = Functions::flattenSingleValue($characters); if (is_bool($characters)) { - if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { - $characters = (int) $characters; - } else { - $characters = ($characters) ? Calculation::getTRUE() : Calculation::getFALSE(); - } + $characters = self::convertBooleanValue($characters); } $character = $characters; @@ -126,11 +131,7 @@ class TextData $aArgs = Functions::flattenArray($args); foreach ($aArgs as $arg) { if (is_bool($arg)) { - if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { - $arg = (int) $arg; - } else { - $arg = ($arg) ? Calculation::getTRUE() : Calculation::getFALSE(); - } + $arg = self::convertBooleanValue($arg); } $returnValue .= $arg; } @@ -197,7 +198,7 @@ class TextData } if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) { - if (StringHelper::countCharacters($needle) == 0) { + if (StringHelper::countCharacters($needle) === 0) { return $offset; } @@ -232,7 +233,7 @@ class TextData } if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) { - if (StringHelper::countCharacters($needle) == 0) { + if (StringHelper::countCharacters($needle) === 0) { return $offset; } @@ -265,14 +266,19 @@ class TextData if (!is_numeric($value) || !is_numeric($decimals)) { return Functions::NAN(); } - $decimals = floor($decimals); + $decimals = (int) floor($decimals); $valueResult = round($value, $decimals); if ($decimals < 0) { $decimals = 0; } if (!$no_commas) { - $valueResult = number_format($valueResult, $decimals); + $valueResult = number_format( + $valueResult, + $decimals, + StringHelper::getDecimalSeparator(), + StringHelper::getThousandsSeparator() + ); } return (string) $valueResult; @@ -659,11 +665,7 @@ class TextData if ($ignoreEmpty && trim($arg) == '') { unset($aArgs[$key]); } elseif (is_bool($arg)) { - if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { - $arg = (int) $arg; - } else { - $arg = ($arg) ? Calculation::getTRUE() : Calculation::getFALSE(); - } + $arg = self::convertBooleanValue($arg); } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php index b8dccf95c2f..341a017979c 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php @@ -36,14 +36,24 @@ class Stack * @param mixed $type * @param mixed $value * @param mixed $reference + * @param null|string $storeKey will store the result under this alias + * @param null|string $onlyIf will only run computation if the matching + * store key is true + * @param null|string $onlyIfNot will only run computation if the matching + * store key is false */ - public function push($type, $value, $reference = null) - { - $this->stack[$this->count++] = [ - 'type' => $type, - 'value' => $value, - 'reference' => $reference, - ]; + public function push( + $type, + $value, + $reference = null, + $storeKey = null, + $onlyIf = null, + $onlyIfNot = null + ) { + $stackItem = $this->getStackItem($type, $value, $reference, $storeKey, $onlyIf, $onlyIfNot); + + $this->stack[$this->count++] = $stackItem; + if ($type == 'Function') { $localeFunction = Calculation::localeFunc($value); if ($localeFunction != $value) { @@ -52,6 +62,35 @@ class Stack } } + public function getStackItem( + $type, + $value, + $reference = null, + $storeKey = null, + $onlyIf = null, + $onlyIfNot = null + ) { + $stackItem = [ + 'type' => $type, + 'value' => $value, + 'reference' => $reference, + ]; + + if (isset($storeKey)) { + $stackItem['storeKey'] = $storeKey; + } + + if (isset($onlyIf)) { + $stackItem['onlyIf'] = $onlyIf; + } + + if (isset($onlyIfNot)) { + $stackItem['onlyIfNot'] = $onlyIfNot; + } + + return $stackItem; + } + /** * Pop the last entry from the stack. * @@ -90,4 +129,21 @@ class Stack $this->stack = []; $this->count = 0; } + + public function __toString() + { + $str = 'Stack: '; + foreach ($this->stack as $index => $item) { + if ($index > $this->count - 1) { + break; + } + $value = $item['value'] ?? 'no value'; + while (is_array($value)) { + $value = array_pop($value); + } + $str .= $value . ' |> '; + } + + return $str; + } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/functionlist.txt b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/functionlist.txt index 4a5cd265ba8..77fd4ee0e4f 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -9,6 +9,7 @@ ADDRESS AMORDEGRC AMORLINC AND +ARABIC AREAS ASC ASIN @@ -22,6 +23,7 @@ AVERAGEA AVERAGEIF AVERAGEIFS BAHTTEXT +BASE BESSELI BESSELJ BESSELK @@ -137,6 +139,8 @@ FISHER FISHERINV FIXED FLOOR +FLOOR.MATH +FLOOR.PRECISE FORECAST FREQUENCY FTEST @@ -224,6 +228,7 @@ LOWER MATCH MAX MAXA +MAXIFS MDETERM MDURATION MEDIAN @@ -231,6 +236,7 @@ MID MIDB MIN MINA +MINIFS MINUTE MINVERSE MIRR diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php index 4052c23cb97..1d28f247e70 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php @@ -118,7 +118,7 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder // Check for time without seconds e.g. '9:45', '09:45' if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { // Convert value to number - list($h, $m) = explode(':', $value); + [$h, $m] = explode(':', $value); $days = $h / 24 + $m / 1440; $cell->setValueExplicit($days, DataType::TYPE_NUMERIC); // Set style @@ -131,7 +131,7 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder // Check for time with seconds '9:45:59', '09:45:59' if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { // Convert value to number - list($h, $m, $s) = explode(':', $value); + [$h, $m, $s] = explode(':', $value); $days = $h / 24 + $m / 1440 + $s / 86400; // Convert value to number $cell->setValueExplicit($days, DataType::TYPE_NUMERIC); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php index 813eee4a091..e618436ed23 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php @@ -67,7 +67,7 @@ class Cell /** * Update the cell into the cell collection. * - * @return self + * @return $this */ public function updateInCollection() { @@ -177,7 +177,7 @@ class Cell * * @throws Exception * - * @return Cell + * @return $this */ public function setValue($pValue) { @@ -217,7 +217,10 @@ class Cell break; case DataType::TYPE_NUMERIC: - $this->value = (float) $pValue; + if (is_string($pValue) && !is_numeric($pValue)) { + throw new Exception('Invalid numeric value for datatype Numeric'); + } + $this->value = 0 + $pValue; break; case DataType::TYPE_FORMULA: @@ -263,7 +266,7 @@ class Cell // We don't yet handle array returns if (is_array($result)) { while (is_array($result)) { - $result = array_pop($result); + $result = array_shift($result); } } } catch (Exception $ex) { @@ -511,7 +514,7 @@ class Cell { if ($mergeRange = $this->getMergeRange()) { $mergeRange = Coordinate::splitRange($mergeRange); - list($startCell) = $mergeRange[0]; + [$startCell] = $mergeRange[0]; if ($this->getCoordinate() === $startCell) { return true; } @@ -569,7 +572,7 @@ class Cell */ public function isInRange($pRange) { - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange); // Translate properties $myColumn = Coordinate::columnIndexFromString($this->getColumn()); @@ -669,7 +672,7 @@ class Cell * * @param mixed $pAttributes * - * @return Cell + * @return $this */ public function setFormulaAttributes($pAttributes) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php index 5e20ec6d9dc..cc0543f6ab4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php @@ -71,7 +71,7 @@ abstract class Coordinate } // Split out any worksheet name from the reference - list($worksheet, $pCoordinateString) = Worksheet::extractSheetTitle($pCoordinateString, true); + [$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, true); if ($worksheet > '') { $worksheet .= '!'; } @@ -102,13 +102,13 @@ abstract class Coordinate } // Split out any worksheet name from the coordinate - list($worksheet, $pCoordinateString) = Worksheet::extractSheetTitle($pCoordinateString, true); + [$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, true); if ($worksheet > '') { $worksheet .= '!'; } // Create absolute coordinate - list($column, $row) = self::coordinateFromString($pCoordinateString); + [$column, $row] = self::coordinateFromString($pCoordinateString); $column = ltrim($column, '$'); $row = ltrim($row, '$'); @@ -187,7 +187,7 @@ abstract class Coordinate if (strpos($pRange, ':') === false) { $rangeA = $rangeB = $pRange; } else { - list($rangeA, $rangeB) = explode(':', $pRange); + [$rangeA, $rangeB] = explode(':', $pRange); } // Calculate range outer borders @@ -211,7 +211,7 @@ abstract class Coordinate public static function rangeDimension($pRange) { // Calculate range outer borders - list($rangeStart, $rangeEnd) = self::rangeBoundaries($pRange); + [$rangeStart, $rangeEnd] = self::rangeBoundaries($pRange); return [($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1)]; } @@ -238,7 +238,7 @@ abstract class Coordinate if (strpos($pRange, ':') === false) { $rangeA = $rangeB = $pRange; } else { - list($rangeA, $rangeB) = explode(':', $pRange); + [$rangeA, $rangeB] = explode(':', $pRange); } return [self::coordinateFromString($rangeA), self::coordinateFromString($rangeB)]; @@ -376,9 +376,9 @@ abstract class Coordinate } // Range... - list($rangeStart, $rangeEnd) = $range; - list($startColumn, $startRow) = self::coordinateFromString($rangeStart); - list($endColumn, $endRow) = self::coordinateFromString($rangeEnd); + [$rangeStart, $rangeEnd] = $range; + [$startColumn, $startRow] = self::coordinateFromString($rangeStart); + [$endColumn, $endRow] = self::coordinateFromString($rangeEnd); $startColumnIndex = self::columnIndexFromString($startColumn); $endColumnIndex = self::columnIndexFromString($endColumn); ++$endColumnIndex; @@ -432,7 +432,7 @@ abstract class Coordinate continue; } - list($column, $row) = self::coordinateFromString($coord); + [$column, $row] = self::coordinateFromString($coord); $row = (int) (ltrim($row, '$')); $hashCode = $column . '-' . (is_object($value) ? $value->getHashCode() : $value); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php index a041ea0e0ab..dfeb024c928 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php @@ -142,7 +142,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setFormula1($value) { @@ -166,7 +166,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setFormula2($value) { @@ -190,7 +190,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setType($value) { @@ -214,7 +214,7 @@ class DataValidation * * @param string $value see self::STYLE_* * - * @return DataValidation + * @return $this */ public function setErrorStyle($value) { @@ -238,7 +238,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setOperator($value) { @@ -262,7 +262,7 @@ class DataValidation * * @param bool $value * - * @return DataValidation + * @return $this */ public function setAllowBlank($value) { @@ -286,7 +286,7 @@ class DataValidation * * @param bool $value * - * @return DataValidation + * @return $this */ public function setShowDropDown($value) { @@ -310,7 +310,7 @@ class DataValidation * * @param bool $value * - * @return DataValidation + * @return $this */ public function setShowInputMessage($value) { @@ -334,7 +334,7 @@ class DataValidation * * @param bool $value * - * @return DataValidation + * @return $this */ public function setShowErrorMessage($value) { @@ -358,7 +358,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setErrorTitle($value) { @@ -382,7 +382,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setError($value) { @@ -406,7 +406,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setPromptTitle($value) { @@ -430,7 +430,7 @@ class DataValidation * * @param string $value * - * @return DataValidation + * @return $this */ public function setPrompt($value) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php index 0e6433a4ec8..cd05cf8bdf9 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php @@ -51,16 +51,16 @@ class DefaultValueBinder implements IValueBinder // Match the value against a few data types if ($pValue === null) { return DataType::TYPE_NULL; + } elseif (is_float($pValue) || is_int($pValue)) { + return DataType::TYPE_NUMERIC; + } elseif (is_bool($pValue)) { + return DataType::TYPE_BOOL; } elseif ($pValue === '') { return DataType::TYPE_STRING; } elseif ($pValue instanceof RichText) { return DataType::TYPE_INLINE; - } elseif ($pValue[0] === '=' && strlen($pValue) > 1) { + } elseif (is_string($pValue) && $pValue[0] === '=' && strlen($pValue) > 1) { return DataType::TYPE_FORMULA; - } elseif (is_bool($pValue)) { - return DataType::TYPE_BOOL; - } elseif (is_float($pValue) || is_int($pValue)) { - return DataType::TYPE_NUMERIC; } elseif (preg_match('/^[\+\-]?(\d+\\.?\d*|\d*\\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?$/', $pValue)) { $tValue = ltrim($pValue, '+-'); if (is_string($pValue) && $tValue[0] === '0' && strlen($tValue) > 1 && $tValue[1] !== '.') { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php index e17c20d9be0..003d51014d9 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php @@ -46,7 +46,7 @@ class Hyperlink * * @param string $value * - * @return Hyperlink + * @return $this */ public function setUrl($value) { @@ -70,7 +70,7 @@ class Hyperlink * * @param string $value * - * @return Hyperlink + * @return $this */ public function setTooltip($value) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php index 3d1dd22262d..66242e3409c 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php @@ -354,7 +354,7 @@ class Axis extends Properties * * @param int $shadow_presets * - * @return Axis + * @return $this */ private function setShadowPresetsProperties($shadow_presets) { @@ -370,7 +370,7 @@ class Axis extends Properties * @param array $properties_map * @param mixed &$reference * - * @return Axis + * @return $this */ private function setShadowProperiesMapValues(array $properties_map, &$reference = null) { @@ -402,7 +402,7 @@ class Axis extends Properties * @param int $alpha * @param string $type * - * @return Axis + * @return $this */ private function setShadowColor($color, $alpha, $type) { @@ -416,7 +416,7 @@ class Axis extends Properties * * @param float $blur * - * @return Axis + * @return $this */ private function setShadowBlur($blur) { @@ -432,7 +432,7 @@ class Axis extends Properties * * @param int $angle * - * @return Axis + * @return $this */ private function setShadowAngle($angle) { @@ -448,7 +448,7 @@ class Axis extends Properties * * @param float $distance * - * @return Axis + * @return $this */ private function setShadowDistance($distance) { @@ -506,7 +506,7 @@ class Axis extends Properties * * @param float $size * - * @return Axis + * @return $this */ private function setGlowSize($size) { @@ -524,7 +524,7 @@ class Axis extends Properties * @param int $alpha * @param string $type * - * @return Axis + * @return $this */ private function setGlowColor($color, $alpha, $type) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php index 3d09a041d57..59c9ed5d67e 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php @@ -156,7 +156,7 @@ class Chart * @param null|GridLines $majorGridlines * @param null|GridLines $minorGridlines */ - public function __construct($name, Title $title = null, Legend $legend = null, PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = '0', Title $xAxisLabel = null, Title $yAxisLabel = null, Axis $xAxis = null, Axis $yAxis = null, GridLines $majorGridlines = null, GridLines $minorGridlines = null) + public function __construct($name, Title $title = null, Legend $legend = null, PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = 'gap', Title $xAxisLabel = null, Title $yAxisLabel = null, Axis $xAxis = null, Axis $yAxis = null, GridLines $majorGridlines = null, GridLines $minorGridlines = null) { $this->name = $name; $this->title = $title; @@ -197,7 +197,7 @@ class Chart * * @param Worksheet $pValue * - * @return Chart + * @return $this */ public function setWorksheet(Worksheet $pValue = null) { @@ -221,7 +221,7 @@ class Chart * * @param Title $title * - * @return Chart + * @return $this */ public function setTitle(Title $title) { @@ -245,7 +245,7 @@ class Chart * * @param Legend $legend * - * @return Chart + * @return $this */ public function setLegend(Legend $legend) { @@ -269,7 +269,7 @@ class Chart * * @param Title $label * - * @return Chart + * @return $this */ public function setXAxisLabel(Title $label) { @@ -293,7 +293,7 @@ class Chart * * @param Title $label * - * @return Chart + * @return $this */ public function setYAxisLabel(Title $label) { @@ -327,7 +327,7 @@ class Chart * * @param bool $plotVisibleOnly * - * @return Chart + * @return $this */ public function setPlotVisibleOnly($plotVisibleOnly) { @@ -351,7 +351,7 @@ class Chart * * @param string $displayBlanksAs * - * @return Chart + * @return $this */ public function setDisplayBlanksAs($displayBlanksAs) { @@ -423,7 +423,7 @@ class Chart * @param int $xOffset * @param int $yOffset * - * @return Chart + * @return $this */ public function setTopLeftPosition($cell, $xOffset = null, $yOffset = null) { @@ -467,7 +467,7 @@ class Chart * * @param string $cell * - * @return Chart + * @return $this */ public function setTopLeftCell($cell) { @@ -482,7 +482,7 @@ class Chart * @param int $xOffset * @param int $yOffset * - * @return Chart + * @return $this */ public function setTopLeftOffset($xOffset, $yOffset) { @@ -541,7 +541,7 @@ class Chart * @param int $xOffset * @param int $yOffset * - * @return Chart + * @return $this */ public function setBottomRightPosition($cell, $xOffset = null, $yOffset = null) { @@ -593,7 +593,7 @@ class Chart * @param int $xOffset * @param int $yOffset * - * @return Chart + * @return $this */ public function setBottomRightOffset($xOffset, $yOffset) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php index 8056bbeea27..c20efabe808 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php @@ -157,7 +157,7 @@ class DataSeries * * @param string $plotType * - * @return DataSeries + * @return $this */ public function setPlotType($plotType) { @@ -181,7 +181,7 @@ class DataSeries * * @param string $groupingType * - * @return DataSeries + * @return $this */ public function setPlotGrouping($groupingType) { @@ -205,7 +205,7 @@ class DataSeries * * @param string $plotDirection * - * @return DataSeries + * @return $this */ public function setPlotDirection($plotDirection) { @@ -297,7 +297,7 @@ class DataSeries * * @param null|string $plotStyle * - * @return DataSeries + * @return $this */ public function setPlotStyle($plotStyle) { @@ -360,7 +360,7 @@ class DataSeries * * @param bool $smoothLine * - * @return DataSeries + * @return $this */ public function setSmoothLine($smoothLine) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php index e82b7efecfb..ec40cb84248 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php @@ -117,7 +117,7 @@ class DataSeriesValues * * @throws Exception * - * @return DataSeriesValues + * @return $this */ public function setDataType($dataType) { @@ -144,7 +144,7 @@ class DataSeriesValues * * @param string $dataSource * - * @return DataSeriesValues + * @return $this */ public function setDataSource($dataSource) { @@ -168,7 +168,7 @@ class DataSeriesValues * * @param string $marker * - * @return DataSeriesValues + * @return $this */ public function setPointMarker($marker) { @@ -192,7 +192,7 @@ class DataSeriesValues * * @param string $formatCode * - * @return DataSeriesValues + * @return $this */ public function setFormatCode($formatCode) { @@ -275,7 +275,7 @@ class DataSeriesValues * * @param int $width * - * @return DataSeriesValues + * @return $this */ public function setLineWidth($width) { @@ -346,7 +346,7 @@ class DataSeriesValues * * @param array $dataValues * - * @return DataSeriesValues + * @return $this */ public function setDataValues($dataValues) { @@ -370,13 +370,13 @@ class DataSeriesValues if ($flatten) { $this->dataValues = Functions::flattenArray($newDataValues); foreach ($this->dataValues as &$dataValue) { - if ((!empty($dataValue)) && ($dataValue[0] == '#')) { + if (is_string($dataValue) && !empty($dataValue) && $dataValue[0] == '#') { $dataValue = 0.0; } } unset($dataValue); } else { - list($worksheet, $cellRange) = Worksheet::extractSheetTitle($this->dataSource, true); + [$worksheet, $cellRange] = Worksheet::extractSheetTitle($this->dataSource, true); $dimensions = Coordinate::rangeDimension(str_replace('$', '', $cellRange)); if (($dimensions[0] == 1) || ($dimensions[1] == 1)) { $this->dataValues = Functions::flattenArray($newDataValues); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php index 8cc83e5540c..b07fcae595a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php @@ -91,7 +91,7 @@ class GridLines extends Properties /** * Change Object State to True. * - * @return GridLines + * @return $this */ private function activateObject() { @@ -229,7 +229,7 @@ class GridLines extends Properties * * @param float $size * - * @return GridLines + * @return $this */ private function setGlowSize($size) { @@ -245,7 +245,7 @@ class GridLines extends Properties * @param int $alpha * @param string $type * - * @return GridLines + * @return $this */ private function setGlowColor($color, $alpha, $type) { @@ -305,7 +305,7 @@ class GridLines extends Properties * * @param int $shadow_presets * - * @return GridLines + * @return $this */ private function setShadowPresetsProperties($shadow_presets) { @@ -321,7 +321,7 @@ class GridLines extends Properties * @param array $properties_map * @param mixed &$reference * - * @return GridLines + * @return $this */ private function setShadowProperiesMapValues(array $properties_map, &$reference = null) { @@ -353,7 +353,7 @@ class GridLines extends Properties * @param int $alpha * @param string $type * - * @return GridLines + * @return $this */ private function setShadowColor($color, $alpha, $type) { @@ -375,7 +375,7 @@ class GridLines extends Properties * * @param float $blur * - * @return GridLines + * @return $this */ private function setShadowBlur($blur) { @@ -391,7 +391,7 @@ class GridLines extends Properties * * @param int $angle * - * @return GridLines + * @return $this */ private function setShadowAngle($angle) { @@ -407,7 +407,7 @@ class GridLines extends Properties * * @param float $distance * - * @return GridLines + * @return $this */ private function setShadowDistance($distance) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php index a8a96d2f1cb..3e989c6d588 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php @@ -153,7 +153,7 @@ class Layout * * @param string $value * - * @return Layout + * @return $this */ public function setLayoutTarget($value) { @@ -177,7 +177,7 @@ class Layout * * @param string $value * - * @return Layout + * @return $this */ public function setXMode($value) { @@ -201,7 +201,7 @@ class Layout * * @param string $value * - * @return Layout + * @return $this */ public function setYMode($value) { @@ -225,7 +225,7 @@ class Layout * * @param float $value * - * @return Layout + * @return $this */ public function setXPosition($value) { @@ -249,7 +249,7 @@ class Layout * * @param float $value * - * @return Layout + * @return $this */ public function setYPosition($value) { @@ -273,7 +273,7 @@ class Layout * * @param float $value * - * @return Layout + * @return $this */ public function setWidth($value) { @@ -297,7 +297,7 @@ class Layout * * @param float $value * - * @return Layout + * @return $this */ public function setHeight($value) { @@ -322,7 +322,7 @@ class Layout * * @param bool $value Show legend key * - * @return Layout + * @return $this */ public function setShowLegendKey($value) { @@ -347,7 +347,7 @@ class Layout * * @param bool $value Show val * - * @return Layout + * @return $this */ public function setShowVal($value) { @@ -372,7 +372,7 @@ class Layout * * @param bool $value Show cat name * - * @return Layout + * @return $this */ public function setShowCatName($value) { @@ -397,7 +397,7 @@ class Layout * * @param bool $value Show series name * - * @return Layout + * @return $this */ public function setShowSerName($value) { @@ -422,7 +422,7 @@ class Layout * * @param bool $value Show percentage * - * @return Layout + * @return $this */ public function setShowPercent($value) { @@ -447,7 +447,7 @@ class Layout * * @param bool $value Show bubble size * - * @return Layout + * @return $this */ public function setShowBubbleSize($value) { @@ -472,7 +472,7 @@ class Layout * * @param bool $value Show leader lines * - * @return Layout + * @return $this */ public function setShowLeaderLines($value) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php index b98c638df76..9da4aa3297a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php @@ -94,7 +94,7 @@ class PlotArea * * @param DataSeries[] $plotSeries * - * @return PlotArea + * @return $this */ public function setPlotSeries(array $plotSeries) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php index c0445d49f9a..9dcab049d2e 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php @@ -442,7 +442,7 @@ class JpGraph implements IRenderer $seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]); } elseif ($scatterStyle == 'smoothMarker') { $spline = new \Spline($dataValuesY, $dataValuesX); - list($splineDataY, $splineDataX) = $spline->Get(count($dataValuesX) * self::$width / 20); + [$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20); $lplot = new \LinePlot($splineDataX, $splineDataY); $lplot->SetColor(self::$colourSet[self::$plotColour]); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php index f53c6b37bdd..650bcdc1521 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php @@ -45,7 +45,7 @@ class Title * * @param string $caption * - * @return Title + * @return $this */ public function setCaption($caption) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php index 46d3cf7e14e..7f34c2315c5 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php @@ -16,8 +16,6 @@ abstract class CellsFactory * */ public static function getInstance(Worksheet $parent) { - $instance = new Cells($parent, Settings::getCache()); - - return $instance; + return new Cells($parent, Settings::getCache()); } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php index 1b5ab1fd2c1..8041ddaf3e8 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php @@ -96,7 +96,7 @@ class Comment implements IComparable * * @param string $author * - * @return Comment + * @return $this */ public function setAuthor($author) { @@ -120,7 +120,7 @@ class Comment implements IComparable * * @param RichText $pValue * - * @return Comment + * @return $this */ public function setText(RichText $pValue) { @@ -144,7 +144,7 @@ class Comment implements IComparable * * @param string $width * - * @return Comment + * @return $this */ public function setWidth($width) { @@ -168,7 +168,7 @@ class Comment implements IComparable * * @param string $value * - * @return Comment + * @return $this */ public function setHeight($value) { @@ -192,7 +192,7 @@ class Comment implements IComparable * * @param string $value * - * @return Comment + * @return $this */ public function setMarginLeft($value) { @@ -216,7 +216,7 @@ class Comment implements IComparable * * @param string $value * - * @return Comment + * @return $this */ public function setMarginTop($value) { @@ -240,7 +240,7 @@ class Comment implements IComparable * * @param bool $value * - * @return Comment + * @return $this */ public function setVisible($value) { @@ -264,7 +264,7 @@ class Comment implements IComparable * * @param string $alignment see Style\Alignment::HORIZONTAL_* * - * @return Comment + * @return $this */ public function setAlignment($alignment) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php index 1a432db0497..58fd2ef60cb 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php @@ -122,7 +122,7 @@ class Properties * * @param string $creator * - * @return Properties + * @return $this */ public function setCreator($creator) { @@ -146,7 +146,7 @@ class Properties * * @param string $pValue * - * @return Properties + * @return $this */ public function setLastModifiedBy($pValue) { @@ -170,7 +170,7 @@ class Properties * * @param int|string $time * - * @return Properties + * @return $this */ public function setCreated($time) { @@ -204,7 +204,7 @@ class Properties * * @param int|string $time * - * @return Properties + * @return $this */ public function setModified($time) { @@ -238,7 +238,7 @@ class Properties * * @param string $title * - * @return Properties + * @return $this */ public function setTitle($title) { @@ -262,7 +262,7 @@ class Properties * * @param string $description * - * @return Properties + * @return $this */ public function setDescription($description) { @@ -286,7 +286,7 @@ class Properties * * @param string $subject * - * @return Properties + * @return $this */ public function setSubject($subject) { @@ -310,7 +310,7 @@ class Properties * * @param string $keywords * - * @return Properties + * @return $this */ public function setKeywords($keywords) { @@ -334,7 +334,7 @@ class Properties * * @param string $category * - * @return Properties + * @return $this */ public function setCategory($category) { @@ -358,7 +358,7 @@ class Properties * * @param string $company * - * @return Properties + * @return $this */ public function setCompany($company) { @@ -382,7 +382,7 @@ class Properties * * @param string $manager * - * @return Properties + * @return $this */ public function setManager($manager) { @@ -453,7 +453,7 @@ class Properties * 'd' : Date/Time * 'b' : Boolean * - * @return Properties + * @return $this */ public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php index 1682678c2e7..cef3db8c44c 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php @@ -75,7 +75,7 @@ class Security * * @param bool $pValue * - * @return Security + * @return $this */ public function setLockRevision($pValue) { @@ -99,7 +99,7 @@ class Security * * @param bool $pValue * - * @return Security + * @return $this */ public function setLockStructure($pValue) { @@ -123,7 +123,7 @@ class Security * * @param bool $pValue * - * @return Security + * @return $this */ public function setLockWindows($pValue) { @@ -148,7 +148,7 @@ class Security * @param string $pValue * @param bool $pAlreadyHashed If the password has already been hashed, set this to true * - * @return Security + * @return $this */ public function setRevisionsPassword($pValue, $pAlreadyHashed = false) { @@ -176,7 +176,7 @@ class Security * @param string $pValue * @param bool $pAlreadyHashed If the password has already been hashed, set this to true * - * @return Security + * @return $this */ public function setWorkbookPassword($pValue, $pAlreadyHashed = false) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DocumentGenerator.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DocumentGenerator.php new file mode 100644 index 00000000000..de6f313f49c --- /dev/null +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DocumentGenerator.php @@ -0,0 +1,111 @@ + $category) { + $result .= "\n"; + $result .= "## {$categoryConstant}\n"; + $result .= "\n"; + $lengths = [20, 42]; + $result .= self::tableRow($lengths, ['Excel Function', 'PhpSpreadsheet Function']) . "\n"; + $result .= self::tableRow($lengths, null) . "\n"; + foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) { + if ($category === $functionInfo['category']) { + $phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']); + $result .= self::tableRow($lengths, [$excelFunction, $phpFunction]) . "\n"; + } + } + } + + return $result; + } + + /** + * @throws ReflectionException + * + * @return array + */ + private static function getCategories(): array + { + return (new ReflectionClass(Category::class))->getConstants(); + } + + private static function tableRow(array $lengths, array $values = null): string + { + $result = ''; + foreach (array_map(null, $lengths, $values ?? []) as $i => [$length, $value]) { + $pad = $value === null ? '-' : ' '; + if ($i > 0) { + $result .= '|' . $pad; + } + $result .= str_pad($value ?? '', $length, $pad); + } + + return rtrim($result, ' '); + } + + private static function getPhpSpreadsheetFunctionText($functionCall): string + { + if (is_string($functionCall)) { + return $functionCall; + } + if ($functionCall === [Functions::class, 'DUMMY']) { + return '**Not yet Implemented**'; + } + if (is_array($functionCall)) { + return "\\{$functionCall[0]}::{$functionCall[1]}"; + } + + throw new UnexpectedValueException( + '$functionCall is of type ' . gettype($functionCall) . '. string or array expected' + ); + } + + /** + * @param array[] $phpSpreadsheetFunctions + * + * @throws ReflectionException + * + * @return string + */ + public static function generateFunctionListByName(array $phpSpreadsheetFunctions): string + { + $categoryConstants = array_flip(self::getCategories()); + $result = "# Function list by name\n"; + $lastAlphabet = null; + foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) { + $lengths = [20, 31, 42]; + if ($lastAlphabet !== $excelFunction[0]) { + $lastAlphabet = $excelFunction[0]; + $result .= "\n"; + $result .= "## {$lastAlphabet}\n"; + $result .= "\n"; + $result .= self::tableRow($lengths, ['Excel Function', 'Category', 'PhpSpreadsheet Function']) . "\n"; + $result .= self::tableRow($lengths, null) . "\n"; + } + $category = $categoryConstants[$functionInfo['category']]; + $phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']); + $result .= self::tableRow($lengths, [$excelFunction, $category, $phpFunction]) . "\n"; + } + + return $result; + } +} diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php index a116334a4ef..4266ea546ad 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php @@ -52,9 +52,8 @@ abstract class IOFactory // Instantiate writer $className = self::$writers[$writerType]; - $writer = new $className($spreadsheet); - return $writer; + return new $className($spreadsheet); } /** @@ -74,9 +73,8 @@ abstract class IOFactory // Instantiate reader $className = self::$readers[$readerType]; - $reader = new $className(); - return $reader; + return new $className(); } /** diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php index 1f94d5a4ed2..e539b7c5304 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php @@ -82,7 +82,7 @@ class NamedRange * * @param string $value * - * @return NamedRange + * @return $this */ public function setName($value) { @@ -123,7 +123,7 @@ class NamedRange * * @param Worksheet $value * - * @return NamedRange + * @return $this */ public function setWorksheet(Worksheet $value = null) { @@ -149,7 +149,7 @@ class NamedRange * * @param string $value * - * @return NamedRange + * @return $this */ public function setRange($value) { @@ -175,7 +175,7 @@ class NamedRange * * @param bool $value * - * @return NamedRange + * @return $this */ public function setLocalOnly($value) { @@ -200,7 +200,7 @@ class NamedRange * * @param null|Worksheet $value * - * @return NamedRange + * @return $this */ public function setScope(Worksheet $value = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php index 81ca1a8cf3e..47134098818 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php @@ -70,7 +70,7 @@ class Csv extends BaseReader * * @param string $pValue Input encoding, eg: 'UTF-8' * - * @return Csv + * @return $this */ public function setInputEncoding($pValue) { @@ -175,9 +175,8 @@ class Csv extends BaseReader } } foreach ($potentialDelimiters as $delimiter) { - $counts[$delimiter][] = isset($countLine[$delimiter]) - ? $countLine[$delimiter] - : 0; + $counts[$delimiter][] = $countLine[$delimiter] + ?? 0; } } @@ -416,7 +415,7 @@ class Csv extends BaseReader * * @param string $delimiter Delimiter, eg: ',' * - * @return CSV + * @return $this */ public function setDelimiter($delimiter) { @@ -440,7 +439,7 @@ class Csv extends BaseReader * * @param string $enclosure Enclosure, defaults to " * - * @return CSV + * @return $this */ public function setEnclosure($enclosure) { @@ -467,7 +466,7 @@ class Csv extends BaseReader * * @param int $pValue Sheet index * - * @return CSV + * @return $this */ public function setSheetIndex($pValue) { @@ -481,7 +480,7 @@ class Csv extends BaseReader * * @param bool $contiguous * - * @return Csv + * @return $this */ public function setContiguous($contiguous) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php index 7445ef1bf25..44ab701d133 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php @@ -267,7 +267,7 @@ class Gnumeric extends BaseReader break; case 'user-defined': - list(, $attrName) = explode(':', $attributes['name']); + [, $attrName] = explode(':', $attributes['name']); switch ($attrName) { case 'publisher': $docProps->setCompany(trim($propertyValue)); @@ -879,7 +879,7 @@ class Gnumeric extends BaseReader private static function parseGnumericColour($gnmColour) { - list($gnmR, $gnmG, $gnmB) = explode(':', $gnmColour); + [$gnmR, $gnmG, $gnmB] = explode(':', $gnmColour); $gnmR = substr(str_pad($gnmR, 4, '0', STR_PAD_RIGHT), 0, 2); $gnmG = substr(str_pad($gnmG, 4, '0', STR_PAD_RIGHT), 0, 2); $gnmB = substr(str_pad($gnmB, 4, '0', STR_PAD_RIGHT), 0, 2); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php index 2e823f03bb5..a255cfd9eb8 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php @@ -223,7 +223,7 @@ class Html extends BaseReader * * @param string $pValue Input encoding, eg: 'ANSI' * - * @return Html + * @return $this */ public function setInputEncoding($pValue) { @@ -374,8 +374,9 @@ class Html extends BaseReader // no break case 'br': if ($this->tableLevel > 0) { - // If we're inside a table, replace with a \n + // If we're inside a table, replace with a \n and set the cell to wrap $cellContent .= "\n"; + $sheet->getStyle($column . $row)->getAlignment()->setWrapText(true); } else { // Otherwise flush our existing content and move the row cursor on $this->flushCell($sheet, $column, $row, $cellContent); @@ -489,22 +490,22 @@ class Html extends BaseReader case 'td': $this->processDomElement($child, $sheet, $row, $column, $cellContent); - // apply inline style - $this->applyInlineStyle($sheet, $row, $column, $attributeArray); - while (isset($this->rowspan[$column . $row])) { ++$column; } + // apply inline style + $this->applyInlineStyle($sheet, $row, $column, $attributeArray); + $this->flushCell($sheet, $column, $row, $cellContent); if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) { //create merging rowspan and colspan $columnTo = $column; - for ($i = 0; $i < $attributeArray['colspan'] - 1; ++$i) { + for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) { ++$columnTo; } - $range = $column . $row . ':' . $columnTo . ($row + $attributeArray['rowspan'] - 1); + $range = $column . $row . ':' . $columnTo . ($row + (int) $attributeArray['rowspan'] - 1); foreach (Coordinate::extractAllCellReferencesInRange($range) as $value) { $this->rowspan[$value] = true; } @@ -512,7 +513,7 @@ class Html extends BaseReader $column = $columnTo; } elseif (isset($attributeArray['rowspan'])) { //create merging rowspan - $range = $column . $row . ':' . $column . ($row + $attributeArray['rowspan'] - 1); + $range = $column . $row . ':' . $column . ($row + (int) $attributeArray['rowspan'] - 1); foreach (Coordinate::extractAllCellReferencesInRange($range) as $value) { $this->rowspan[$value] = true; } @@ -520,7 +521,7 @@ class Html extends BaseReader } elseif (isset($attributeArray['colspan'])) { //create merging colspan $columnTo = $column; - for ($i = 0; $i < $attributeArray['colspan'] - 1; ++$i) { + for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) { ++$columnTo; } $sheet->mergeCells($column . $row . ':' . $columnTo . $row); @@ -591,28 +592,63 @@ class Html extends BaseReader throw new Exception($pFilename . ' is an Invalid HTML file.'); } - // Create new sheet - while ($spreadsheet->getSheetCount() <= $this->sheetIndex) { - $spreadsheet->createSheet(); - } - $spreadsheet->setActiveSheetIndex($this->sheetIndex); - - // Create a new DOM object + // Create a new DOM object $dom = new DOMDocument(); - // Reload the HTML file into the DOM object + // Reload the HTML file into the DOM object $loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scanFile($pFilename), 'HTML-ENTITIES', 'UTF-8')); if ($loaded === false) { throw new Exception('Failed to load ' . $pFilename . ' as a DOM Document'); } - // Discard white space - $dom->preserveWhiteSpace = false; + return $this->loadDocument($dom, $spreadsheet); + } + + /** + * Spreadsheet from content. + * + * @param string $content + * @param null|Spreadsheet $spreadsheet + * + * @return Spreadsheet + */ + public function loadFromString($content, ?Spreadsheet $spreadsheet = null): Spreadsheet + { + // Create a new DOM object + $dom = new DOMDocument(); + // Reload the HTML file into the DOM object + $loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scan($content), 'HTML-ENTITIES', 'UTF-8')); + if ($loaded === false) { + throw new Exception('Failed to load content as a DOM Document'); + } + + return $this->loadDocument($dom, $spreadsheet ?? new Spreadsheet()); + } + + /** + * Loads PhpSpreadsheet from DOMDocument into PhpSpreadsheet instance. + * + * @param DOMDocument $document + * @param Spreadsheet $spreadsheet + * + * @throws \PhpOffice\PhpSpreadsheet\Exception + * + * @return Spreadsheet + */ + private function loadDocument(DOMDocument $document, Spreadsheet $spreadsheet): Spreadsheet + { + while ($spreadsheet->getSheetCount() <= $this->sheetIndex) { + $spreadsheet->createSheet(); + } + $spreadsheet->setActiveSheetIndex($this->sheetIndex); + + // Discard white space + $document->preserveWhiteSpace = false; $row = 0; $column = 'A'; $content = ''; $this->rowspan = []; - $this->processDomElement($dom, $spreadsheet->getActiveSheet(), $row, $column, $content); + $this->processDomElement($document, $spreadsheet->getActiveSheet(), $row, $column, $content); // Return return $spreadsheet; @@ -633,7 +669,7 @@ class Html extends BaseReader * * @param int $pValue Sheet index * - * @return HTML + * @return $this */ public function setSheetIndex($pValue) { @@ -919,7 +955,7 @@ class Html extends BaseReader */ private function setBorderStyle(Style $cellStyle, $styleValue, $type) { - list(, $borderStyle, $color) = explode(' ', $styleValue); + [, $borderStyle, $color] = explode(' ', $styleValue); $cellStyle->applyFromArray([ 'borders' => [ diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php index 51462c2003e..5fff07aa383 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php @@ -490,7 +490,7 @@ class Ods extends BaseReader $dateObj = new DateTime($value, $GMT); $dateObj->setTimeZone($timezoneObj); - list($year, $month, $day, $hour, $minute, $second) = explode( + [$year, $month, $day, $hour, $minute, $second] = explode( ' ', $dateObj->format('Y m d H i s') ); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php index 8b6122c56e7..c5c7caf8439 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php @@ -19,12 +19,11 @@ class Properties $docProps = $this->spreadsheet->getProperties(); $officeProperty = $xml->children($namespacesMeta['office']); foreach ($officeProperty as $officePropertyData) { - /** @var \SimpleXMLElement $officePropertyData */ - $officePropertiesDC = (object) []; + // @var \SimpleXMLElement $officePropertyData if (isset($namespacesMeta['dc'])) { $officePropertiesDC = $officePropertyData->children($namespacesMeta['dc']); + $this->setCoreProperties($docProps, $officePropertiesDC); } - $this->setCoreProperties($docProps, $officePropertiesDC); $officePropertyMeta = (object) []; if (isset($namespacesMeta['dc'])) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php index c1013c2eb22..9912e9376bd 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php @@ -83,7 +83,7 @@ class Slk extends BaseReader * * @param string $pValue Input encoding, eg: 'ANSI' * - * @return Slk + * @return $this */ public function setInputEncoding($pValue) { @@ -384,7 +384,7 @@ class Slk extends BaseReader break; case 'W': - list($startCol, $endCol, $columnWidth) = explode(' ', substr($rowDatum, 1)); + [$startCol, $endCol, $columnWidth] = explode(' ', substr($rowDatum, 1)); break; case 'S': @@ -485,7 +485,7 @@ class Slk extends BaseReader * * @param int $pValue Sheet index * - * @return Slk + * @return $this */ public function setSheetIndex($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php index bd2c9c1db5b..313d7216ba5 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php @@ -1089,8 +1089,8 @@ class Xls extends BaseReader } // calculate the width and height of the shape - list($startColumn, $startRow) = Coordinate::coordinateFromString($spContainer->getStartCoordinates()); - list($endColumn, $endRow) = Coordinate::coordinateFromString($spContainer->getEndCoordinates()); + [$startColumn, $startRow] = Coordinate::coordinateFromString($spContainer->getStartCoordinates()); + [$endColumn, $endRow] = Coordinate::coordinateFromString($spContainer->getEndCoordinates()); $startOffsetX = $spContainer->getStartOffsetX(); $startOffsetY = $spContainer->getStartOffsetY(); @@ -1175,7 +1175,7 @@ class Xls extends BaseReader // treat SHAREDFMLA records if ($this->version == self::XLS_BIFF8) { foreach ($this->sharedFormulaParts as $cell => $baseCell) { - list($column, $row) = Coordinate::coordinateFromString($cell); + [$column, $row] = Coordinate::coordinateFromString($cell); if (($this->getReadFilter() !== null) && $this->getReadFilter()->readCell($column, $row, $this->phpSheet->getTitle())) { $formula = $this->getFormulaFromStructure($this->sharedFormulas[$baseCell], $cell); $this->phpSheet->getCell($cell)->setValueExplicit('=' . $formula, DataType::TYPE_FORMULA); @@ -1251,8 +1251,8 @@ class Xls extends BaseReader $coordinateStrings = explode(':', $extractedRange); if (count($coordinateStrings) == 2) { - list($firstColumn, $firstRow) = Coordinate::coordinateFromString($coordinateStrings[0]); - list($lastColumn, $lastRow) = Coordinate::coordinateFromString($coordinateStrings[1]); + [$firstColumn, $firstRow] = Coordinate::coordinateFromString($coordinateStrings[0]); + [$lastColumn, $lastRow] = Coordinate::coordinateFromString($coordinateStrings[1]); if ($firstColumn == 'A' and $lastColumn == 'IV') { // then we have repeating rows @@ -3825,7 +3825,7 @@ class Xls extends BaseReader } } - if (!$this->readDataOnly && !$emptyCell) { + if (!$this->readDataOnly && !$emptyCell && isset($this->mapCellXfIndex[$xfIndex])) { // add style information $cell->setXfIndex($this->mapCellXfIndex[$xfIndex]); } @@ -5279,12 +5279,10 @@ class Xls extends BaseReader $nextIdentifier = self::getUInt2d($this->data, $this->pos); } while ($nextIdentifier == self::XLS_TYPE_CONTINUE); - $splicedData = [ + return [ 'recordData' => $data, 'spliceOffsets' => $spliceOffsets, ]; - - return $splicedData; } /** @@ -5355,12 +5353,12 @@ class Xls extends BaseReader $formulaStrings = []; foreach ($tokens as $token) { // initialize spaces - $space0 = isset($space0) ? $space0 : ''; // spaces before next token, not tParen - $space1 = isset($space1) ? $space1 : ''; // carriage returns before next token, not tParen - $space2 = isset($space2) ? $space2 : ''; // spaces before opening parenthesis - $space3 = isset($space3) ? $space3 : ''; // carriage returns before opening parenthesis - $space4 = isset($space4) ? $space4 : ''; // spaces before closing parenthesis - $space5 = isset($space5) ? $space5 : ''; // carriage returns before closing parenthesis + $space0 = $space0 ?? ''; // spaces before next token, not tParen + $space1 = $space1 ?? ''; // carriage returns before next token, not tParen + $space2 = $space2 ?? ''; // spaces before opening parenthesis + $space3 = $space3 ?? ''; // carriage returns before opening parenthesis + $space4 = $space4 ?? ''; // spaces before closing parenthesis + $space5 = $space5 ?? ''; // carriage returns before closing parenthesis switch ($token['name']) { case 'tAdd': // addition @@ -7145,7 +7143,7 @@ class Xls extends BaseReader */ private function readBIFF8CellAddressB($cellAddressStructure, $baseCell = 'A1') { - list($baseCol, $baseRow) = Coordinate::coordinateFromString($baseCell); + [$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell); $baseCol = Coordinate::columnIndexFromString($baseCol) - 1; // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) @@ -7328,7 +7326,7 @@ class Xls extends BaseReader */ private function readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') { - list($baseCol, $baseRow) = Coordinate::coordinateFromString($baseCell); + [$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell); $baseCol = Coordinate::columnIndexFromString($baseCol) - 1; // TODO: if cell range is just a single cell, should this funciton diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php index 5372fef9c13..566e9fbbf08 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php @@ -77,34 +77,17 @@ class Xlsx extends BaseReader { File::assertFile($pFilename); - $xl = false; - // Load file + $result = false; $zip = new ZipArchive(); - if ($zip->open($pFilename) === true) { - // check if it is an OOXML archive - $rels = simplexml_load_string( - $this->securityScanner->scan( - $this->getFromZipArchive($zip, '_rels/.rels') - ), - 'SimpleXMLElement', - Settings::getLibXmlLoaderOptions() - ); - if ($rels !== false) { - foreach ($rels->Relationship as $rel) { - switch ($rel['Type']) { - case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument': - if (basename($rel['Target']) == 'workbook.xml') { - $xl = true; - } - break; - } - } - } + if ($zip->open($pFilename) === true) { + $workbookBasename = $this->getWorkbookBaseName($zip); + $result = !empty($workbookBasename); + $zip->close(); } - return $xl; + return $result; } /** @@ -357,8 +340,9 @@ class Xlsx extends BaseReader // Read the theme first, because we need the colour scheme when reading the styles //~ http://schemas.openxmlformats.org/package/2006/relationships" + $workbookBasename = $this->getWorkbookBaseName($zip); $wbRels = simplexml_load_string( - $this->securityScanner->scan($this->getFromZipArchive($zip, 'xl/_rels/workbook.xml.rels')), + $this->securityScanner->scan($this->getFromZipArchive($zip, "xl/_rels/${workbookBasename}.rels")), 'SimpleXMLElement', Settings::getLibXmlLoaderOptions() ); @@ -445,18 +429,20 @@ class Xlsx extends BaseReader $sharedStrings = []; $xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); - //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main" - $xmlStrings = simplexml_load_string( - $this->securityScanner->scan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), - 'SimpleXMLElement', - Settings::getLibXmlLoaderOptions() - ); - if (isset($xmlStrings, $xmlStrings->si)) { - foreach ($xmlStrings->si as $val) { - if (isset($val->t)) { - $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); - } elseif (isset($val->r)) { - $sharedStrings[] = $this->parseRichText($val); + if ($xpath) { + //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main" + $xmlStrings = simplexml_load_string( + $this->securityScanner->scan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")), + 'SimpleXMLElement', + Settings::getLibXmlLoaderOptions() + ); + if (isset($xmlStrings, $xmlStrings->si)) { + foreach ($xmlStrings->si as $val) { + if (isset($val->t)) { + $sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t); + } elseif (isset($val->r)) { + $sharedStrings[] = $this->parseRichText($val); + } } } } @@ -743,15 +729,6 @@ class Xlsx extends BaseReader // read empty cells or the cells are not empty if ($this->readEmptyCells || ($value !== null && $value !== '')) { - // Check for numeric values - if (is_numeric($value) && $cellDataType != 's') { - if ($value == (int) $value) { - $value = (int) $value; - } elseif ($value == (float) $value) { - $value = (float) $value; - } - } - // Rich text? if ($value instanceof RichText && $this->readDataOnly) { $value = $value->getPlainText(); @@ -1352,7 +1329,7 @@ class Xlsx extends BaseReader $rangeSets = preg_split("/('?(?:.*?)'?(?:![A-Z0-9]+:[A-Z0-9]+)),?/", $extractedRange, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); $newRangeSets = []; foreach ($rangeSets as $rangeSet) { - list($sheetName, $rangeSet) = Worksheet::extractSheetTitle($rangeSet, true); + [$sheetName, $rangeSet] = Worksheet::extractSheetTitle($rangeSet, true); if (strpos($rangeSet, ':') === false) { $rangeSet = $rangeSet . ':' . $rangeSet; } @@ -1426,7 +1403,7 @@ class Xlsx extends BaseReader $locatedSheet = $excel->getSheetByName($extractedSheetName); // Modify range - list($worksheetName, $extractedRange) = Worksheet::extractSheetTitle($extractedRange, true); + [$worksheetName, $extractedRange] = Worksheet::extractSheetTitle($extractedRange, true); } if ($locatedSheet !== null) { @@ -1437,7 +1414,7 @@ class Xlsx extends BaseReader } } - if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) { + if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && isset($xmlWorkbook->bookViews->workbookView)) { $workbookView = $xmlWorkbook->bookViews->workbookView; // active sheet index @@ -1643,8 +1620,6 @@ class Xlsx extends BaseReader $docStyle->getFill()->setFillType($patternType); if ($style->fill->patternFill->fgColor) { $docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true)); - } else { - $docStyle->getFill()->getStartColor()->setARGB('FF000000'); } if ($style->fill->patternFill->bgColor) { $docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true)); @@ -1841,7 +1816,7 @@ class Xlsx extends BaseReader private static function getArrayItem($array, $key = 0) { - return isset($array[$key]) ? $array[$key] : null; + return $array[$key] ?? null; } private static function dirAdd($base, $add) @@ -1851,7 +1826,7 @@ class Xlsx extends BaseReader private static function toCSSArray($style) { - $style = trim(str_replace(["\r", "\n"], '', $style), ';'); + $style = self::stripWhiteSpaceFromStyleString($style); $temp = explode(';', $style); $style = []; @@ -1880,6 +1855,11 @@ class Xlsx extends BaseReader return $style; } + public static function stripWhiteSpaceFromStyleString($string) + { + return trim(str_replace(["\r", "\n", ' '], '', $string), ';'); + } + private static function boolean($value) { if (is_object($value)) { @@ -2026,4 +2006,38 @@ class Xlsx extends BaseReader return (bool) $xsdBoolean; } + + /** + * @param ZipArchive $zip Opened zip archive + * + * @return string basename of the used excel workbook + */ + private function getWorkbookBaseName(ZipArchive $zip) + { + $workbookBasename = ''; + + // check if it is an OOXML archive + $rels = simplexml_load_string( + $this->securityScanner->scan( + $this->getFromZipArchive($zip, '_rels/.rels') + ), + 'SimpleXMLElement', + Settings::getLibXmlLoaderOptions() + ); + if ($rels !== false) { + foreach ($rels->Relationship as $rel) { + switch ($rel['Type']) { + case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument': + $basename = basename($rel['Target']); + if (preg_match('/workbook.*\.xml/', $basename)) { + $workbookBasename = $basename; + } + + break; + } + } + } + + return $workbookBasename; + } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php index 6929758dfe9..69d5f69e0a4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php @@ -20,7 +20,8 @@ class AutoFilter public function load() { - $autoFilterRange = (string) $this->worksheetXml->autoFilter['ref']; + // Remove all "$" in the auto filter range + $autoFilterRange = preg_replace('/\$/', '', $this->worksheetXml->autoFilter['ref']); if (strpos($autoFilterRange, ':') !== false) { $this->readAutoFilter($autoFilterRange, $this->worksheetXml); } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php index b3de5d1cde6..722b77952a4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php @@ -36,6 +36,8 @@ class ConditionalStyles if (((string) $cfRule['type'] == Conditional::CONDITION_NONE || (string) $cfRule['type'] == Conditional::CONDITION_CELLIS || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT + || (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS + || (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS || (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION) && isset($this->dxfs[(int) ($cfRule['dxfId'])])) { $conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php index bc6bba2cdb2..bf8e57d807a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php @@ -86,6 +86,6 @@ class Properties private static function getArrayItem(array $array, $key = 0) { - return isset($array[$key]) ? $array[$key] : null; + return $array[$key] ?? null; } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php index 2caaec3108e..88c01ead373 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php @@ -24,6 +24,7 @@ class SheetViews extends BaseParserClass $this->gridLines(); $this->headers(); $this->direction(); + $this->showZeros(); if (isset($this->sheetViewXml->pane)) { $this->pane(); @@ -92,6 +93,15 @@ class SheetViews extends BaseParserClass } } + private function showZeros() + { + if (isset($this->sheetViewXml['showZeros'])) { + $this->worksheet->getSheetView()->setShowZeros( + self::boolean((string) $this->sheetViewXml['showZeros']) + ); + } + } + private function pane() { $xSplit = 0; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php index c06564a3d11..40106258c40 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php @@ -8,6 +8,7 @@ use PhpOffice\PhpSpreadsheet\Style\Borders; use PhpOffice\PhpSpreadsheet\Style\Color; use PhpOffice\PhpSpreadsheet\Style\Fill; use PhpOffice\PhpSpreadsheet\Style\Font; +use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Style\Protection; use PhpOffice\PhpSpreadsheet\Style\Style; @@ -71,6 +72,17 @@ class Styles extends BaseParserClass } } + private static function readNumberFormat(NumberFormat $numfmtStyle, \SimpleXMLElement $numfmtStyleXml) + { + if ($numfmtStyleXml->count() === 0) { + return; + } + $numfmt = $numfmtStyleXml->attributes(); + if ($numfmt->count() > 0 && isset($numfmt['formatCode'])) { + $numfmtStyle->setFormatCode((string) $numfmt['formatCode']); + } + } + private static function readFillStyle(Fill $fillStyle, \SimpleXMLElement $fillStyleXml) { if ($fillStyleXml->gradientFill) { @@ -149,7 +161,11 @@ class Styles extends BaseParserClass private function readStyle(Style $docStyle, $style) { - $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + if ($style->numFmt instanceof \SimpleXMLElement) { + self::readNumberFormat($docStyle->getNumberFormat(), $style->numFmt); + } else { + $docStyle->getNumberFormat()->setFormatCode($style->numFmt); + } if (isset($style->font)) { self::readFontStyle($docStyle->getFont(), $style->font); @@ -163,7 +179,7 @@ class Styles extends BaseParserClass self::readBorderStyle($docStyle->getBorders(), $style->border); } - if (isset($style->alignment)) { + if (isset($style->alignment->alignment)) { self::readAlignmentStyle($docStyle->getAlignment(), $style->alignment); } @@ -260,6 +276,6 @@ class Styles extends BaseParserClass private static function getArrayItem($array, $key = 0) { - return isset($array[$key]) ? $array[$key] : null; + return $array[$key] ?? null; } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php index 8ab7a9c3954..b4fffa4fb8b 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php @@ -285,9 +285,8 @@ class Xml extends BaseReader { $pixels = ($widthUnits / 256) * 7; $offsetWidthUnits = $widthUnits % 256; - $pixels += round($offsetWidthUnits / (256 / 7)); - return $pixels; + return $pixels + round($offsetWidthUnits / (256 / 7)); } protected static function hex2str($hex) diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php index 13dbe042a75..143e80d8ce9 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php @@ -82,11 +82,8 @@ class ReferenceHelper */ public static function cellSort($a, $b) { - // TODO Scrutinizer doesn't like sscanf($a, '%[A-Z]%d', $ac, $ar), and we can't use short list() syntax - // [$ac, $ar] = sscanf($a, '%[A-Z]%d') while retaining PHP 5.6 support. - // Switch when we drop support for 5.6 - list($ac, $ar) = sscanf($a, '%[A-Z]%d'); - list($bc, $br) = sscanf($b, '%[A-Z]%d'); + [$ac, $ar] = sscanf($a, '%[A-Z]%d'); + [$bc, $br] = sscanf($b, '%[A-Z]%d'); if ($ar === $br) { return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); @@ -106,11 +103,8 @@ class ReferenceHelper */ public static function cellReverseSort($a, $b) { - // TODO Scrutinizer doesn't like sscanf($a, '%[A-Z]%d', $ac, $ar), and we can't use short list() syntax - // [$ac, $ar] = sscanf($a, '%[A-Z]%d') while retaining PHP 5.6 support. - // Switch when we drop support for 5.6 - list($ac, $ar) = sscanf($a, '%[A-Z]%d'); - list($bc, $br) = sscanf($b, '%[A-Z]%d'); + [$ac, $ar] = sscanf($a, '%[A-Z]%d'); + [$bc, $br] = sscanf($b, '%[A-Z]%d'); if ($ar === $br) { return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); @@ -132,7 +126,7 @@ class ReferenceHelper */ private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { - list($cellColumn, $cellRow) = Coordinate::coordinateFromString($cellAddress); + [$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress); $cellColumnIndex = Coordinate::columnIndexFromString($cellColumn); // Is cell within the range of rows/columns if we're deleting if ($pNumRows < 0 && @@ -319,7 +313,7 @@ class ReferenceHelper if (!empty($aColumnDimensions)) { foreach ($aColumnDimensions as $objColumnDimension) { $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); - list($newReference) = Coordinate::coordinateFromString($newReference); + [$newReference] = Coordinate::coordinateFromString($newReference); if ($objColumnDimension->getColumnIndex() != $newReference) { $objColumnDimension->setColumnIndex($newReference); } @@ -344,7 +338,7 @@ class ReferenceHelper if (!empty($aRowDimensions)) { foreach ($aRowDimensions as $objRowDimension) { $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); - list(, $newReference) = Coordinate::coordinateFromString($newReference); + [, $newReference] = Coordinate::coordinateFromString($newReference); if ($objRowDimension->getRowIndex() != $newReference) { $objRowDimension->setRowIndex($newReference); } @@ -378,7 +372,7 @@ class ReferenceHelper $allCoordinates = $pSheet->getCoordinates(); // Get coordinate of $pBefore - list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore); + [$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($pBefore); $beforeColumnIndex = Coordinate::columnIndexFromString($beforeColumn); // Clear cells if we are removing columns or rows @@ -539,7 +533,7 @@ class ReferenceHelper $row = 0; sscanf($pBefore, '%[A-Z]%d', $column, $row); $columnIndex = Coordinate::columnIndexFromString($column); - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($autoFilterRange); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($autoFilterRange); if ($columnIndex <= $rangeEnd[0]) { if ($pNumCols < 0) { // If we're actually deleting any columns that fall within the autofilter range, @@ -707,7 +701,7 @@ class ReferenceHelper if (($match[2] == '') || (trim($match[2], "'") == $sheetName)) { $toString = ($match[2] > '') ? $match[2] . '!' : ''; $toString .= $modified3 . ':' . $modified4; - list($column, $row) = Coordinate::coordinateFromString($match[3]); + [$column, $row] = Coordinate::coordinateFromString($match[3]); // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more $column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000; $row = trim($row, '$') + 10000000; @@ -733,7 +727,7 @@ class ReferenceHelper if (($match[2] == '') || (trim($match[2], "'") == $sheetName)) { $toString = ($match[2] > '') ? $match[2] . '!' : ''; $toString .= $modified3; - list($column, $row) = Coordinate::coordinateFromString($match[3]); + [$column, $row] = Coordinate::coordinateFromString($match[3]); // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more $column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000; $row = trim($row, '$') + 10000000; @@ -881,10 +875,10 @@ class ReferenceHelper } // Get coordinate of $pBefore - list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore); + [$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($pBefore); // Get coordinate of $pCellReference - list($newColumn, $newRow) = Coordinate::coordinateFromString($pCellReference); + [$newColumn, $newRow] = Coordinate::coordinateFromString($pCellReference); // Verify which parts should be updated $updateColumn = (($newColumn[0] != '$') && ($beforeColumn[0] != '$') && (Coordinate::columnIndexFromString($newColumn) >= Coordinate::columnIndexFromString($beforeColumn))); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php index 76a04d549f5..6e90fa355fa 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php @@ -47,7 +47,7 @@ class RichText implements IComparable * * @param ITextElement $pText Rich text element * - * @return RichText + * @return $this */ public function addText(ITextElement $pText) { @@ -133,7 +133,7 @@ class RichText implements IComparable * * @param ITextElement[] $textElements Array of elements * - * @return RichText + * @return $this */ public function setRichTextElements(array $textElements) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php index b4996235f33..aa4a8e462d3 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php @@ -40,7 +40,7 @@ class Run extends TextElement implements ITextElement * * @param Font $pFont Font * - * @return ITextElement + * @return $this */ public function setFont(Font $pFont = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php index d9ad0d7f5ed..f8be5d55b0e 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php @@ -37,7 +37,7 @@ class TextElement implements ITextElement * * @param $text string Text * - * @return ITextElement + * @return $this */ public function setText($text) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php index c297dd682ea..03fa6ac2cbe 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php @@ -30,7 +30,6 @@ class Settings * 7.2 < 7.2.1 * 7.1 < 7.1.13 * 7.0 < 7.0.27 - * 5.6 ANY * then you may need to disable this check to prevent unwanted behaviour in other threads * SECURITY WARNING: Changing this flag is not recommended. * @@ -122,7 +121,6 @@ class Settings * 7.2 < 7.2.1 * 7.1 < 7.1.13 * 7.0 < 7.0.27 - * 5.6 ANY * then you may need to disable this check to prevent unwanted behaviour in other threads * SECURITY WARNING: Changing this flag to false is not recommended. * diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php index 8abcef2e192..bee13e2921e 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php @@ -298,9 +298,7 @@ class Font $upperLeftCornerX = $textBox[6]; // Consider the rotation when calculating the width - $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); - - return $textWidth; + return max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); } /** diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php index b3d82d466cc..a67b6c2de52 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/Matrix.php @@ -174,7 +174,7 @@ class Matrix switch ($match) { //A($i0...; $j0...) case 'integer,integer': - list($i0, $j0) = $args; + [$i0, $j0] = $args; if ($i0 >= 0) { $m = $this->m - $i0; } else { @@ -197,7 +197,7 @@ class Matrix break; //A($i0...$iF; $j0...$jF) case 'integer,integer,integer,integer': - list($i0, $iF, $j0, $jF) = $args; + [$i0, $iF, $j0, $jF] = $args; if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { @@ -220,7 +220,7 @@ class Matrix break; //$R = array of row indices; $C = array of column indices case 'array,array': - list($RL, $CL) = $args; + [$RL, $CL] = $args; if (count($RL) > 0) { $m = count($RL); } else { @@ -243,7 +243,7 @@ class Matrix break; //A($i0...$iF); $CL = array of column indices case 'integer,integer,array': - list($i0, $iF, $CL) = $args; + [$i0, $iF, $CL] = $args; if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { @@ -266,7 +266,7 @@ class Matrix break; //$RL = array of row indices case 'array,integer,integer': - list($RL, $j0, $jF) = $args; + [$RL, $j0, $jF] = $args; if (count($RL) > 0) { $m = count($RL); } else { @@ -524,7 +524,7 @@ class Matrix * * @param mixed $B Matrix/Array * - * @return Matrix Sum + * @return $this */ public function plusEquals(...$args) { @@ -628,7 +628,7 @@ class Matrix * * @param mixed $B Matrix/Array * - * @return Matrix Sum + * @return $this */ public function minusEquals(...$args) { @@ -734,7 +734,7 @@ class Matrix * * @param mixed $B Matrix/Array * - * @return Matrix Matrix Aij + * @return $this */ public function arrayTimesEquals(...$args) { @@ -1091,7 +1091,7 @@ class Matrix * * @param mixed $B Matrix/Array * - * @return Matrix Sum + * @return $this */ public function power(...$args) { @@ -1150,7 +1150,7 @@ class Matrix * * @param mixed $B Matrix/Array * - * @return Matrix Sum + * @return $this */ public function concat(...$args) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php index e666d74b6a3..3bb8a10ef91 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/JAMA/QRDecomposition.php @@ -60,7 +60,7 @@ class QRDecomposition { if ($A instanceof Matrix) { // Initialize. - $this->QR = $A->getArrayCopy(); + $this->QR = $A->getArray(); $this->m = $A->getRowDimension(); $this->n = $A->getColumnDimension(); // Main loop. diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php index f09fbc92adc..efa7522fad6 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php @@ -253,7 +253,7 @@ class OLE */ private static function _readInt1($fh) { - list(, $tmp) = unpack('c', fread($fh, 1)); + [, $tmp] = unpack('c', fread($fh, 1)); return $tmp; } @@ -267,7 +267,7 @@ class OLE */ private static function _readInt2($fh) { - list(, $tmp) = unpack('v', fread($fh, 2)); + [, $tmp] = unpack('v', fread($fh, 2)); return $tmp; } @@ -281,7 +281,7 @@ class OLE */ private static function _readInt4($fh) { - list(, $tmp) = unpack('V', fread($fh, 4)); + [, $tmp] = unpack('V', fread($fh, 4)); return $tmp; } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php index 578e08fafe3..c52cea239fd 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php @@ -118,7 +118,7 @@ class Root extends PPS $aList = []; PPS::_savePpsSetPnt($aList, [$this]); // calculate values for header - list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo); + [$iSBDcnt, $iBBcnt, $iPPScnt] = $this->_calcSize($aList); //, $rhInfo); // Save Header $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt); @@ -149,7 +149,7 @@ class Root extends PPS public function _calcSize(&$raList) { // Calculate Basic Setting - list($iSBDcnt, $iBBcnt, $iPPScnt) = [0, 0, 0]; + [$iSBDcnt, $iBBcnt, $iPPScnt] = [0, 0, 0]; $iSmallLen = 0; $iSBcnt = 0; $iCount = count($raList); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php index a5702775074..d949203babc 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php @@ -430,9 +430,7 @@ class StringHelper // characters $chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8'); - $data = pack('vC', $ln, 0x0001) . $chars; - - return $data; + return pack('vC', $ln, 0x0001) . $chars; } /** diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php index 177779f8f10..b8ce5e2daa8 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php @@ -211,7 +211,7 @@ class Xls */ public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height) { - list($column, $row) = Coordinate::coordinateFromString($coordinates); + [$column, $row] = Coordinate::coordinateFromString($coordinates); $col_start = Coordinate::columnIndexFromString($column); $row_start = $row - 1; @@ -269,7 +269,7 @@ class Xls $startCoordinates = Coordinate::stringFromColumnIndex($col_start) . ($row_start + 1); $endCoordinates = Coordinate::stringFromColumnIndex($col_end) . ($row_end + 1); - $twoAnchor = [ + return [ 'startCoordinates' => $startCoordinates, 'startOffsetX' => $x1, 'startOffsetY' => $y1, @@ -277,7 +277,5 @@ class Xls 'endOffsetX' => $x2, 'endOffsetY' => $y2, ]; - - return $twoAnchor; } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php index 8eadcbe8b1a..d33a98719fd 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php @@ -721,7 +721,7 @@ class Spreadsheet { $worksheetCount = count($this->workSheetCollection); for ($i = 0; $i < $worksheetCount; ++$i) { - if ($this->workSheetCollection[$i]->getTitle() === $pName) { + if ($this->workSheetCollection[$i]->getTitle() === trim($pName, "'")) { return $this->workSheetCollection[$i]; } } @@ -955,7 +955,7 @@ class Spreadsheet * @param string $namedRange * @param null|Worksheet $pSheet scope: use null for global scope * - * @return Spreadsheet + * @return $this */ public function removeNamedRange($namedRange, Worksheet $pSheet = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php index b4df792b167..5eb7c2b0f47 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php @@ -140,7 +140,7 @@ class Alignment extends Supervisor * * @throws PhpSpreadsheetException * - * @return Alignment + * @return $this */ public function applyFromArray(array $pStyles) { @@ -193,7 +193,7 @@ class Alignment extends Supervisor * * @param string $pValue see self::HORIZONTAL_* * - * @return Alignment + * @return $this */ public function setHorizontal($pValue) { @@ -230,7 +230,7 @@ class Alignment extends Supervisor * * @param string $pValue see self::VERTICAL_* * - * @return Alignment + * @return $this */ public function setVertical($pValue) { @@ -269,7 +269,7 @@ class Alignment extends Supervisor * * @throws PhpSpreadsheetException * - * @return Alignment + * @return $this */ public function setTextRotation($pValue) { @@ -312,7 +312,7 @@ class Alignment extends Supervisor * * @param bool $pValue * - * @return Alignment + * @return $this */ public function setWrapText($pValue) { @@ -348,7 +348,7 @@ class Alignment extends Supervisor * * @param bool $pValue * - * @return Alignment + * @return $this */ public function setShrinkToFit($pValue) { @@ -384,7 +384,7 @@ class Alignment extends Supervisor * * @param int $pValue * - * @return Alignment + * @return $this */ public function setIndent($pValue) { @@ -424,7 +424,7 @@ class Alignment extends Supervisor * * @param int $pValue * - * @return Alignment + * @return $this */ public function setReadOrder($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php index c957cf595a9..5fa0cae70d9 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php @@ -127,7 +127,7 @@ class Border extends Supervisor * * @throws PhpSpreadsheetException * - * @return Border + * @return $this */ public function applyFromArray(array $pStyles) { @@ -166,7 +166,7 @@ class Border extends Supervisor * When passing a boolean, FALSE equates Border::BORDER_NONE * and TRUE to Border::BORDER_MEDIUM * - * @return Border + * @return $this */ public function setBorderStyle($pValue) { @@ -202,7 +202,7 @@ class Border extends Supervisor * * @throws PhpSpreadsheetException * - * @return Border + * @return $this */ public function setColor(Color $pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php index a1d6759b936..8f005a9980a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php @@ -197,7 +197,7 @@ class Borders extends Supervisor * * @throws PhpSpreadsheetException * - * @return Borders + * @return $this */ public function applyFromArray(array $pStyles) { @@ -382,7 +382,7 @@ class Borders extends Supervisor * * @param int $pValue see self::DIAGONAL_* * - * @return Borders + * @return $this */ public function setDiagonalDirection($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php index 8a1812d20b7..ab22cbe3248 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php @@ -6,6 +6,17 @@ use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; class Color extends Supervisor { + const NAMED_COLORS = [ + 'Black', + 'White', + 'Red', + 'Green', + 'Blue', + 'Yellow', + 'Magenta', + 'Cyan', + ]; + // Colors const COLOR_BLACK = 'FF000000'; const COLOR_WHITE = 'FFFFFFFF'; @@ -95,7 +106,7 @@ class Color extends Supervisor * * @throws PhpSpreadsheetException * - * @return Color + * @return $this */ public function applyFromArray(array $pStyles) { @@ -132,7 +143,7 @@ class Color extends Supervisor * * @param string $pValue see self::COLOR_* * - * @return Color + * @return $this */ public function setARGB($pValue) { @@ -168,7 +179,7 @@ class Color extends Supervisor * * @param string $pValue RGB value * - * @return Color + * @return $this */ public function setRGB($pValue) { @@ -198,11 +209,8 @@ class Color extends Supervisor private static function getColourComponent($RGB, $offset, $hex = true) { $colour = substr($RGB, $offset, 2); - if (!$hex) { - $colour = hexdec($colour); - } - return $colour; + return ($hex) ? $colour : hexdec($colour); } /** @@ -257,7 +265,7 @@ class Color extends Supervisor */ public static function changeBrightness($hex, $adjustPercentage) { - $rgba = (strlen($hex) == 8); + $rgba = (strlen($hex) === 8); $red = self::getRed($hex, false); $green = self::getGreen($hex, false); @@ -289,9 +297,9 @@ class Color extends Supervisor } $rgb = strtoupper( - str_pad(dechex($red), 2, '0', 0) . - str_pad(dechex($green), 2, '0', 0) . - str_pad(dechex($blue), 2, '0', 0) + str_pad(dechex((int) $red), 2, '0', 0) . + str_pad(dechex((int) $green), 2, '0', 0) . + str_pad(dechex((int) $blue), 2, '0', 0) ); return (($rgba) ? 'FF' : '') . $rgb; @@ -304,7 +312,7 @@ class Color extends Supervisor * @param bool $background Flag to indicate whether default background or foreground colour * should be returned if the indexed colour doesn't exist * - * @return Color + * @return self */ public static function indexedColor($pIndex, $background = false) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php index 91a000dba4a..ec8c858b03b 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php @@ -12,6 +12,7 @@ class Conditional implements IComparable const CONDITION_CONTAINSTEXT = 'containsText'; const CONDITION_EXPRESSION = 'expression'; const CONDITION_CONTAINSBLANKS = 'containsBlanks'; + const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks'; // Operator types const OPERATOR_NONE = ''; @@ -93,7 +94,7 @@ class Conditional implements IComparable * * @param string $pValue Condition type, see self::CONDITION_* * - * @return Conditional + * @return $this */ public function setConditionType($pValue) { @@ -117,7 +118,7 @@ class Conditional implements IComparable * * @param string $pValue Conditional operator type, see self::OPERATOR_* * - * @return Conditional + * @return $this */ public function setOperatorType($pValue) { @@ -141,7 +142,7 @@ class Conditional implements IComparable * * @param string $value * - * @return Conditional + * @return $this */ public function setText($value) { @@ -165,7 +166,7 @@ class Conditional implements IComparable * * @param bool $value * - * @return Conditional + * @return $this */ public function setStopIfTrue($value) { @@ -189,7 +190,7 @@ class Conditional implements IComparable * * @param string[] $pValue Condition * - * @return Conditional + * @return $this */ public function setConditions($pValue) { @@ -206,7 +207,7 @@ class Conditional implements IComparable * * @param string $pValue Condition * - * @return Conditional + * @return $this */ public function addCondition($pValue) { @@ -230,7 +231,7 @@ class Conditional implements IComparable * * @param Style $pValue * - * @return Conditional + * @return $this */ public function setStyle(Style $pValue = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php index c2ad895ee12..1d6bace147a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php @@ -141,7 +141,7 @@ class Fill extends Supervisor * * @throws PhpSpreadsheetException * - * @return Fill + * @return $this */ public function applyFromArray(array $pStyles) { @@ -188,7 +188,7 @@ class Fill extends Supervisor * * @param string $pValue Fill type, see self::FILL_* * - * @return Fill + * @return $this */ public function setFillType($pValue) { @@ -221,7 +221,7 @@ class Fill extends Supervisor * * @param float $pValue * - * @return Fill + * @return $this */ public function setRotation($pValue) { @@ -252,7 +252,7 @@ class Fill extends Supervisor * * @throws PhpSpreadsheetException * - * @return Fill + * @return $this */ public function setStartColor(Color $pValue) { @@ -286,7 +286,7 @@ class Fill extends Supervisor * * @throws PhpSpreadsheetException * - * @return Fill + * @return $this */ public function setEndColor(Color $pValue) { @@ -313,12 +313,13 @@ class Fill extends Supervisor if ($this->isSupervisor) { return $this->getSharedComponent()->getHashCode(); } - + // Note that we don't care about colours for fill type NONE, but could have duplicate NONEs with + // different hashes if we don't explicitly prevent this return md5( $this->getFillType() . $this->getRotation() . - $this->getStartColor()->getHashCode() . - $this->getEndColor()->getHashCode() . + ($this->getFillType() !== self::FILL_NONE ? $this->getStartColor()->getHashCode() : '') . + ($this->getFillType() !== self::FILL_NONE ? $this->getEndColor()->getHashCode() : '') . __CLASS__ ); } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php index 6d8e23b1954..0341cad0dc4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php @@ -161,7 +161,7 @@ class Font extends Supervisor * * @throws PhpSpreadsheetException * - * @return Font + * @return $this */ public function applyFromArray(array $pStyles) { @@ -219,7 +219,7 @@ class Font extends Supervisor * * @param string $pValue * - * @return Font + * @return $this */ public function setName($pValue) { @@ -255,7 +255,7 @@ class Font extends Supervisor * * @param float $pValue * - * @return Font + * @return $this */ public function setSize($pValue) { @@ -291,7 +291,7 @@ class Font extends Supervisor * * @param bool $pValue * - * @return Font + * @return $this */ public function setBold($pValue) { @@ -327,7 +327,7 @@ class Font extends Supervisor * * @param bool $pValue * - * @return Font + * @return $this */ public function setItalic($pValue) { @@ -363,7 +363,7 @@ class Font extends Supervisor * * @param bool $pValue * - * @return Font + * @return $this */ public function setSuperscript($pValue) { @@ -400,7 +400,7 @@ class Font extends Supervisor * * @param bool $pValue * - * @return Font + * @return $this */ public function setSubscript($pValue) { @@ -439,7 +439,7 @@ class Font extends Supervisor * If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE, * false equates to UNDERLINE_NONE * - * @return Font + * @return $this */ public function setUnderline($pValue) { @@ -477,7 +477,7 @@ class Font extends Supervisor * * @param bool $pValue * - * @return Font + * @return $this */ public function setStrikethrough($pValue) { @@ -512,7 +512,7 @@ class Font extends Supervisor * * @throws PhpSpreadsheetException * - * @return Font + * @return $this */ public function setColor(Color $pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php index 37442249a50..df4ca76f4ff 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php @@ -23,8 +23,8 @@ class NumberFormat extends Supervisor const FORMAT_PERCENTAGE_00 = '0.00%'; const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd'; - const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd'; - const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy'; + const FORMAT_DATE_YYYYMMDD = 'yyyy-mm-dd'; + const FORMAT_DATE_DDMMYYYY = 'dd/mm/yyyy'; const FORMAT_DATE_DMYSLASH = 'd/m/yy'; const FORMAT_DATE_DMYMINUS = 'd-m-yy'; const FORMAT_DATE_DMMINUS = 'd-m'; @@ -43,7 +43,7 @@ class NumberFormat extends Supervisor const FORMAT_DATE_TIME6 = 'h:mm:ss'; const FORMAT_DATE_TIME7 = 'i:s.S'; const FORMAT_DATE_TIME8 = 'h:mm:ss;@'; - const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@'; + const FORMAT_DATE_YYYYMMDDSLASH = 'yyyy/mm/dd;@'; const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-'; const FORMAT_CURRENCY_USD = '$#,##0_-'; @@ -139,7 +139,7 @@ class NumberFormat extends Supervisor * * @throws PhpSpreadsheetException * - * @return NumberFormat + * @return $this */ public function applyFromArray(array $pStyles) { @@ -176,7 +176,7 @@ class NumberFormat extends Supervisor * * @param string $pValue see self::FORMAT_* * - * @return NumberFormat + * @return $this */ public function setFormatCode($pValue) { @@ -213,7 +213,7 @@ class NumberFormat extends Supervisor * * @param int $pValue * - * @return NumberFormat + * @return $this */ public function setBuiltInFormatCode($pValue) { @@ -367,7 +367,7 @@ class NumberFormat extends Supervisor self::fillBuiltInFormatCodes(); // Lookup format code - if (isset(self::$flippedBuiltInFormats[$formatCode])) { + if (array_key_exists($formatCode, self::$flippedBuiltInFormats)) { return self::$flippedBuiltInFormats[$formatCode]; } @@ -551,24 +551,32 @@ class NumberFormat extends Supervisor } } - private static function complexNumberFormatMask($number, $mask) + private static function mergeComplexNumberFormatMasks($numbers, $masks) { - $sign = ($number < 0.0); - $number = abs($number); - if (strpos($mask, '.') !== false) { - $numbers = explode('.', $number . '.0'); - $masks = explode('.', $mask . '.0'); - $result1 = self::complexNumberFormatMask($numbers[0], $masks[0]); - $result2 = strrev(self::complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]))); + $decimalCount = strlen($numbers[1]); + $postDecimalMasks = []; - return (($sign) ? '-' : '') . $result1 . '.' . $result2; - } + do { + $tempMask = array_pop($masks); + $postDecimalMasks[] = $tempMask; + $decimalCount -= strlen($tempMask); + } while ($decimalCount > 0); - $r = preg_match_all('/0+/', $mask, $result, PREG_OFFSET_CAPTURE); - if ($r > 1) { - $result = array_reverse($result[0]); + return [ + implode('.', $masks), + implode('.', array_reverse($postDecimalMasks)), + ]; + } - foreach ($result as $block) { + private static function processComplexNumberFormatMask($number, $mask) + { + $result = $number; + $maskingBlockCount = preg_match_all('/0+/', $mask, $maskingBlocks, PREG_OFFSET_CAPTURE); + + if ($maskingBlockCount > 1) { + $maskingBlocks = array_reverse($maskingBlocks[0]); + + foreach ($maskingBlocks as $block) { $divisor = 1 . $block[0]; $size = strlen($block[0]); $offset = $block[1]; @@ -584,13 +592,134 @@ class NumberFormat extends Supervisor $mask = substr_replace($mask, $number, $offset, 0); } $result = $mask; - } else { - $result = $number; } + return $result; + } + + private static function complexNumberFormatMask($number, $mask, $splitOnPoint = true) + { + $sign = ($number < 0.0); + $number = abs($number); + + if ($splitOnPoint && strpos($mask, '.') !== false && strpos($number, '.') !== false) { + $numbers = explode('.', $number); + $masks = explode('.', $mask); + if (count($masks) > 2) { + $masks = self::mergeComplexNumberFormatMasks($numbers, $masks); + } + $result1 = self::complexNumberFormatMask($numbers[0], $masks[0], false); + $result2 = strrev(self::complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]), false)); + + return (($sign) ? '-' : '') . $result1 . '.' . $result2; + } + + $result = self::processComplexNumberFormatMask($number, $mask); + return (($sign) ? '-' : '') . $result; } + private static function formatStraightNumericValue($value, $format, array $matches, $useThousands, $number_regex) + { + $left = $matches[1]; + $dec = $matches[2]; + $right = $matches[3]; + + // minimun width of formatted number (including dot) + $minWidth = strlen($left) + strlen($dec) + strlen($right); + if ($useThousands) { + $value = number_format( + $value, + strlen($right), + StringHelper::getDecimalSeparator(), + StringHelper::getThousandsSeparator() + ); + $value = preg_replace($number_regex, $value, $format); + } else { + if (preg_match('/[0#]E[+-]0/i', $format)) { + // Scientific format + $value = sprintf('%5.2E', $value); + } elseif (preg_match('/0([^\d\.]+)0/', $format) || substr_count($format, '.') > 1) { + if ($value == (int) $value && substr_count($format, '.') === 1) { + $value *= 10 ** strlen(explode('.', $format)[1]); + } + $value = self::complexNumberFormatMask($value, $format); + } else { + $sprintf_pattern = "%0$minWidth." . strlen($right) . 'f'; + $value = sprintf($sprintf_pattern, $value); + $value = preg_replace($number_regex, $value, $format); + } + } + + return $value; + } + + private static function formatAsNumber($value, $format) + { + if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { + return 'EUR ' . sprintf('%1.2f', $value); + } + + // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols + $format = str_replace(['"', '*'], '', $format); + + // Find out if we need thousands separator + // This is indicated by a comma enclosed by a digit placeholder: + // #,# or 0,0 + $useThousands = preg_match('/(#,#|0,0)/', $format); + if ($useThousands) { + $format = preg_replace('/0,0/', '00', $format); + $format = preg_replace('/#,#/', '##', $format); + } + + // Scale thousands, millions,... + // This is indicated by a number of commas after a digit placeholder: + // #, or 0.0,, + $scale = 1; // same as no scale + $matches = []; + if (preg_match('/(#|0)(,+)/', $format, $matches)) { + $scale = pow(1000, strlen($matches[2])); + + // strip the commas + $format = preg_replace('/0,+/', '0', $format); + $format = preg_replace('/#,+/', '#', $format); + } + + if (preg_match('/#?.*\?\/\?/', $format, $m)) { + if ($value != (int) $value) { + self::formatAsFraction($value, $format); + } + } else { + // Handle the number itself + + // scale number + $value = $value / $scale; + // Strip # + $format = preg_replace('/\\#/', '0', $format); + // Remove locale code [$-###] + $format = preg_replace('/\[\$\-.*\]/', '', $format); + + $n = '/\\[[^\\]]+\\]/'; + $m = preg_replace($n, '', $format); + $number_regex = '/(0+)(\\.?)(0*)/'; + if (preg_match($number_regex, $m, $matches)) { + $value = self::formatStraightNumericValue($value, $format, $matches, $useThousands, $number_regex); + } + } + + if (preg_match('/\[\$(.*)\]/u', $format, $m)) { + // Currency or Accounting + $currencyCode = $m[1]; + [$currencyCode] = explode('-', $currencyCode); + if ($currencyCode == '') { + $currencyCode = StringHelper::getCurrencyCode(); + } + $value = preg_replace('/\[\$([^\]]*)\]/u', $currencyCode, $value); + } + + return $value; + } + /** * Convert a value in a pre-defined format to a PHP string. * @@ -660,7 +789,9 @@ class NumberFormat extends Supervisor // Save format with color information for later use below $formatColor = $format; - + // Strip colour information + $color_regex = '/\[(' . implode('|', Color::NAMED_COLORS) . ')\]/'; + $format = preg_replace($color_regex, '', $format); // Let's begin inspecting the format and converting the value to a formatted string // Check for date/time characters (not inside quotes) @@ -668,105 +799,19 @@ class NumberFormat extends Supervisor // datetime format self::formatAsDate($value, $format); } else { - // Strip color information - $color_regex = '/^\\[[a-zA-Z]+\\]/'; - $format = preg_replace($color_regex, '', $format); - if (preg_match('/%$/', $format)) { + if (substr($format, 0, 1) === '"' && substr($format, -1, 1) === '"') { + $value = substr($format, 1, -1); + } elseif (preg_match('/%$/', $format)) { // % number format self::formatAsPercentage($value, $format); } else { - if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { - $value = 'EUR ' . sprintf('%1.2f', $value); - } else { - // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols - $format = str_replace(['"', '*'], '', $format); - - // Find out if we need thousands separator - // This is indicated by a comma enclosed by a digit placeholder: - // #,# or 0,0 - $useThousands = preg_match('/(#,#|0,0)/', $format); - if ($useThousands) { - $format = preg_replace('/0,0/', '00', $format); - $format = preg_replace('/#,#/', '##', $format); - } - - // Scale thousands, millions,... - // This is indicated by a number of commas after a digit placeholder: - // #, or 0.0,, - $scale = 1; // same as no scale - $matches = []; - if (preg_match('/(#|0)(,+)/', $format, $matches)) { - $scale = pow(1000, strlen($matches[2])); - - // strip the commas - $format = preg_replace('/0,+/', '0', $format); - $format = preg_replace('/#,+/', '#', $format); - } - - if (preg_match('/#?.*\?\/\?/', $format, $m)) { - if ($value != (int) $value) { - self::formatAsFraction($value, $format); - } - } else { - // Handle the number itself - - // scale number - $value = $value / $scale; - - // Strip # - $format = preg_replace('/\\#/', '0', $format); - - // Remove locale code [$-###] - $format = preg_replace('/\[\$\-.*\]/', '', $format); - - $n = '/\\[[^\\]]+\\]/'; - $m = preg_replace($n, '', $format); - $number_regex = '/(0+)(\\.?)(0*)/'; - if (preg_match($number_regex, $m, $matches)) { - $left = $matches[1]; - $dec = $matches[2]; - $right = $matches[3]; - - // minimun width of formatted number (including dot) - $minWidth = strlen($left) + strlen($dec) + strlen($right); - if ($useThousands) { - $value = number_format( - $value, - strlen($right), - StringHelper::getDecimalSeparator(), - StringHelper::getThousandsSeparator() - ); - $value = preg_replace($number_regex, $value, $format); - } else { - if (preg_match('/[0#]E[+-]0/i', $format)) { - // Scientific format - $value = sprintf('%5.2E', $value); - } elseif (preg_match('/0([^\d\.]+)0/', $format)) { - $value = self::complexNumberFormatMask($value, $format); - } else { - $sprintf_pattern = "%0$minWidth." . strlen($right) . 'f'; - $value = sprintf($sprintf_pattern, $value); - $value = preg_replace($number_regex, $value, $format); - } - } - } - } - if (preg_match('/\[\$(.*)\]/u', $format, $m)) { - // Currency or Accounting - $currencyCode = $m[1]; - list($currencyCode) = explode('-', $currencyCode); - if ($currencyCode == '') { - $currencyCode = StringHelper::getCurrencyCode(); - } - $value = preg_replace('/\[\$([^\]]*)\]/u', $currencyCode, $value); - } - } + $value = self::formatAsNumber($value, $format); } } // Additional formatting provided by callback function if ($callBack !== null) { - list($writerInstance, $function) = $callBack; + [$writerInstance, $function] = $callBack; $value = $writerInstance->$function($value, $formatColor); } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php index b5feb53486e..8112bc62049 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php @@ -86,7 +86,7 @@ class Protection extends Supervisor * * @throws PhpSpreadsheetException * - * @return Protection + * @return $this */ public function applyFromArray(array $pStyles) { @@ -123,7 +123,7 @@ class Protection extends Supervisor * * @param string $pValue see self::PROTECTION_* * - * @return Protection + * @return $this */ public function setLocked($pValue) { @@ -156,7 +156,7 @@ class Protection extends Supervisor * * @param string $pValue see self::PROTECTION_* * - * @return Protection + * @return $this */ public function setHidden($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php index fbe07c2cdd2..a37d99b5f58 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php @@ -189,7 +189,7 @@ class Style extends Supervisor * @param array $pStyles Array containing style information * @param bool $pAdvanced advanced mode for setting borders * - * @return Style + * @return $this */ public function applyFromArray(array $pStyles, $pAdvanced = true) { @@ -204,7 +204,7 @@ class Style extends Supervisor $rangeA = $pRange; $rangeB = $pRange; } else { - list($rangeA, $rangeB) = explode(':', $pRange); + [$rangeA, $rangeB] = explode(':', $pRange); } // Calculate range outer borders @@ -485,7 +485,7 @@ class Style extends Supervisor * * @param Font $font * - * @return Style + * @return $this */ public function setFont(Font $font) { @@ -539,7 +539,7 @@ class Style extends Supervisor * * @param Conditional[] $pValue Array of conditional styles * - * @return Style + * @return $this */ public function setConditionalStyles(array $pValue) { @@ -577,7 +577,7 @@ class Style extends Supervisor * * @param bool $pValue * - * @return Style + * @return $this */ public function setQuotePrefix($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php index 2d1a27266b1..1a700974b72 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php @@ -48,7 +48,7 @@ abstract class Supervisor implements IComparable * @param Spreadsheet|Style $parent * @param null|string $parentPropertyName * - * @return Supervisor + * @return $this */ public function bindParent($parent, $parentPropertyName = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php index 494948a77f2..dcbc4da5b43 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php @@ -59,7 +59,7 @@ class AutoFilter * * @param Worksheet $pSheet * - * @return AutoFilter + * @return $this */ public function setParent(Worksheet $pSheet = null) { @@ -85,12 +85,12 @@ class AutoFilter * * @throws PhpSpreadsheetException * - * @return AutoFilter + * @return $this */ public function setRange($pRange) { // extract coordinate - list($worksheet, $pRange) = Worksheet::extractSheetTitle($pRange, true); + [$worksheet, $pRange] = Worksheet::extractSheetTitle($pRange, true); if (strpos($pRange, ':') !== false) { $this->range = $pRange; @@ -105,7 +105,7 @@ class AutoFilter $this->columns = []; } else { // Discard any column rules that are no longer valid within this range - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range); foreach ($this->columns as $key => $value) { $colIndex = Coordinate::columnIndexFromString($key); if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) { @@ -143,7 +143,7 @@ class AutoFilter } $columnIndex = Coordinate::columnIndexFromString($column); - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range); if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) { throw new PhpSpreadsheetException('Column is outside of current autofilter range.'); } @@ -196,7 +196,7 @@ class AutoFilter */ public function getColumnByOffset($pColumnOffset) { - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range); $pColumn = Coordinate::stringFromColumnIndex($rangeStart[0] + $pColumnOffset); return $this->getColumn($pColumn); @@ -210,7 +210,7 @@ class AutoFilter * * @throws PhpSpreadsheetException * - * @return AutoFilter + * @return $this */ public function setColumn($pColumn) { @@ -241,7 +241,7 @@ class AutoFilter * * @throws PhpSpreadsheetException * - * @return AutoFilter + * @return $this */ public function clearColumn($pColumn) { @@ -264,7 +264,7 @@ class AutoFilter * @param string $fromColumn Column name (e.g. A) * @param string $toColumn Column name (e.g. B) * - * @return AutoFilter + * @return $this */ public function shiftColumn($fromColumn, $toColumn) { @@ -357,7 +357,7 @@ class AutoFilter { $dataSet = $ruleSet['filterRules']; $join = $ruleSet['join']; - $customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : false; + $customRuleForBlanks = $ruleSet['customRuleForBlanks'] ?? false; if (!$customRuleForBlanks) { // Blank cells are always ignored, so return a FALSE @@ -617,11 +617,11 @@ class AutoFilter * * @throws PhpSpreadsheetException * - * @return AutoFilter + * @return $this */ public function showHideRows() { - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range); // The heading row should always be visible $this->workSheet->getRowDimension($rangeStart[1])->setVisible(true); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php index b5ab61e9713..3ed7270a147 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php @@ -101,7 +101,7 @@ class Column } /** - * Get AutoFilter Column Index. + * Get AutoFilter column index as string eg: 'A'. * * @return string */ @@ -111,13 +111,13 @@ class Column } /** - * Set AutoFilter Column Index. + * Set AutoFilter column index as string eg: 'A'. * * @param string $pColumn Column (e.g. A) * * @throws PhpSpreadsheetException * - * @return Column + * @return $this */ public function setColumnIndex($pColumn) { @@ -147,7 +147,7 @@ class Column * * @param AutoFilter $pParent * - * @return Column + * @return $this */ public function setParent(AutoFilter $pParent = null) { @@ -173,7 +173,7 @@ class Column * * @throws PhpSpreadsheetException * - * @return Column + * @return $this */ public function setFilterType($pFilterType) { @@ -203,7 +203,7 @@ class Column * * @throws PhpSpreadsheetException * - * @return Column + * @return $this */ public function setJoin($pJoin) { @@ -223,7 +223,7 @@ class Column * * @param string[] $attributes * - * @return Column + * @return $this */ public function setAttributes(array $attributes) { @@ -238,7 +238,7 @@ class Column * @param string $pName Attribute Name * @param string $pValue Attribute Value * - * @return Column + * @return $this */ public function setAttribute($pName, $pValue) { @@ -316,7 +316,7 @@ class Column * * @param Column\Rule $pRule * - * @return Column + * @return $this */ public function addRule(Column\Rule $pRule) { @@ -332,7 +332,7 @@ class Column * * @param int $pIndex Rule index in the ruleset array * - * @return Column + * @return $this */ public function deleteRule($pIndex) { @@ -350,7 +350,7 @@ class Column /** * Delete all AutoFilter Column Rules. * - * @return Column + * @return $this */ public function clearRules() { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php index 450bccdb6ac..09a2bacdd9b 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php @@ -262,7 +262,7 @@ class Rule * * @throws PhpSpreadsheetException * - * @return Rule + * @return $this */ public function setRuleType($pRuleType) { @@ -292,7 +292,7 @@ class Rule * * @throws PhpSpreadsheetException * - * @return Rule + * @return $this */ public function setValue($pValue) { @@ -336,7 +336,7 @@ class Rule * * @throws PhpSpreadsheetException * - * @return Rule + * @return $this */ public function setOperator($pOperator) { @@ -369,7 +369,7 @@ class Rule * * @throws PhpSpreadsheetException * - * @return Rule + * @return $this */ public function setGrouping($pGrouping) { @@ -393,7 +393,7 @@ class Rule * * @throws PhpSpreadsheetException * - * @return Rule + * @return $this */ public function setRule($pOperator, $pValue, $pGrouping = null) { @@ -424,7 +424,7 @@ class Rule * * @param Column $pParent * - * @return Rule + * @return $this */ public function setParent(Column $pParent = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php index 98b689729e1..7d24e4496bd 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php @@ -154,7 +154,7 @@ class BaseDrawing implements IComparable * * @param string $pValue * - * @return BaseDrawing + * @return $this */ public function setName($pValue) { @@ -178,7 +178,7 @@ class BaseDrawing implements IComparable * * @param string $description * - * @return BaseDrawing + * @return $this */ public function setDescription($description) { @@ -205,7 +205,7 @@ class BaseDrawing implements IComparable * * @throws PhpSpreadsheetException * - * @return BaseDrawing + * @return $this */ public function setWorksheet(Worksheet $pValue = null, $pOverrideOld = false) { @@ -253,7 +253,7 @@ class BaseDrawing implements IComparable * * @param string $pValue eg: 'A1' * - * @return BaseDrawing + * @return $this */ public function setCoordinates($pValue) { @@ -277,7 +277,7 @@ class BaseDrawing implements IComparable * * @param int $pValue * - * @return BaseDrawing + * @return $this */ public function setOffsetX($pValue) { @@ -301,7 +301,7 @@ class BaseDrawing implements IComparable * * @param int $pValue * - * @return BaseDrawing + * @return $this */ public function setOffsetY($pValue) { @@ -325,7 +325,7 @@ class BaseDrawing implements IComparable * * @param int $pValue * - * @return BaseDrawing + * @return $this */ public function setWidth($pValue) { @@ -356,7 +356,7 @@ class BaseDrawing implements IComparable * * @param int $pValue * - * @return BaseDrawing + * @return $this */ public function setHeight($pValue) { @@ -386,7 +386,7 @@ class BaseDrawing implements IComparable * @param int $width * @param int $height * - * @return BaseDrawing + * @return $this */ public function setWidthAndHeight($width, $height) { @@ -423,7 +423,7 @@ class BaseDrawing implements IComparable * * @param bool $pValue * - * @return BaseDrawing + * @return $this */ public function setResizeProportional($pValue) { @@ -447,7 +447,7 @@ class BaseDrawing implements IComparable * * @param int $pValue * - * @return BaseDrawing + * @return $this */ public function setRotation($pValue) { @@ -471,7 +471,7 @@ class BaseDrawing implements IComparable * * @param Drawing\Shadow $pValue * - * @return BaseDrawing + * @return $this */ public function setShadow(Drawing\Shadow $pValue = null) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php index 4baaae1f54a..098967f726d 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php @@ -40,7 +40,7 @@ class Column } /** - * Get column index. + * Get column index as string eg: 'A'. * * @return string */ diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php index 7e8f040d26a..d75da898814 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php @@ -59,7 +59,7 @@ class ColumnCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return ColumnCellIterator + * @return $this */ public function resetStart($startRow = 1) { @@ -77,7 +77,7 @@ class ColumnCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return ColumnCellIterator + * @return $this */ public function resetEnd($endRow = null) { @@ -94,7 +94,7 @@ class ColumnCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return ColumnCellIterator + * @return $this */ public function seek($row = 1) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php index e2ea8af15f7..4e87a344c80 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php @@ -42,7 +42,7 @@ class ColumnDimension extends Dimension } /** - * Get ColumnIndex. + * Get column index as string eg: 'A'. * * @return string */ @@ -52,11 +52,11 @@ class ColumnDimension extends Dimension } /** - * Set ColumnIndex. + * Set column index as string eg: 'A'. * * @param string $pValue * - * @return ColumnDimension + * @return $this */ public function setColumnIndex($pValue) { @@ -80,7 +80,7 @@ class ColumnDimension extends Dimension * * @param float $pValue * - * @return ColumnDimension + * @return $this */ public function setWidth($pValue) { @@ -104,7 +104,7 @@ class ColumnDimension extends Dimension * * @param bool $pValue * - * @return ColumnDimension + * @return $this */ public function setAutoSize($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php index d2b57aad2f5..c8913cc164a 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php @@ -66,7 +66,7 @@ class ColumnIterator implements \Iterator * * @throws Exception * - * @return ColumnIterator + * @return $this */ public function resetStart($startColumn = 'A') { @@ -89,7 +89,7 @@ class ColumnIterator implements \Iterator * * @param string $endColumn The column address at which to stop iterating * - * @return ColumnIterator + * @return $this */ public function resetEnd($endColumn = null) { @@ -106,7 +106,7 @@ class ColumnIterator implements \Iterator * * @throws PhpSpreadsheetException * - * @return ColumnIterator + * @return $this */ public function seek($column = 'A') { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php index 697fc97efc3..ce40cf57f72 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php @@ -60,7 +60,7 @@ abstract class Dimension * * @param bool $pValue * - * @return Dimension + * @return $this */ public function setVisible($pValue) { @@ -87,7 +87,7 @@ abstract class Dimension * * @throws PhpSpreadsheetException * - * @return Dimension + * @return $this */ public function setOutlineLevel($pValue) { @@ -115,7 +115,7 @@ abstract class Dimension * * @param bool $pValue * - * @return Dimension + * @return $this */ public function setCollapsed($pValue) { @@ -139,7 +139,7 @@ abstract class Dimension * * @param int $pValue * - * @return Dimension + * @return $this */ public function setXfIndex($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php index ed26006c048..da492b4c300 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php @@ -78,7 +78,7 @@ class Drawing extends BaseDrawing * * @throws PhpSpreadsheetException * - * @return Drawing + * @return $this */ public function setPath($pValue, $pVerifyFile = true) { @@ -88,7 +88,7 @@ class Drawing extends BaseDrawing if ($this->width == 0 && $this->height == 0) { // Get width/height - list($this->width, $this->height) = getimagesize($pValue); + [$this->width, $this->height] = getimagesize($pValue); } } else { throw new PhpSpreadsheetException("File $pValue not found!"); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php index a1e05d60001..c7594dae926 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php @@ -100,7 +100,7 @@ class Shadow implements IComparable * * @param bool $pValue * - * @return Shadow + * @return $this */ public function setVisible($pValue) { @@ -124,7 +124,7 @@ class Shadow implements IComparable * * @param int $pValue * - * @return Shadow + * @return $this */ public function setBlurRadius($pValue) { @@ -148,7 +148,7 @@ class Shadow implements IComparable * * @param int $pValue * - * @return Shadow + * @return $this */ public function setDistance($pValue) { @@ -172,7 +172,7 @@ class Shadow implements IComparable * * @param int $pValue * - * @return Shadow + * @return $this */ public function setDirection($pValue) { @@ -196,7 +196,7 @@ class Shadow implements IComparable * * @param int $pValue * - * @return Shadow + * @return $this */ public function setAlignment($pValue) { @@ -220,7 +220,7 @@ class Shadow implements IComparable * * @param Color $pValue * - * @return Shadow + * @return $this */ public function setColor(Color $pValue = null) { @@ -244,7 +244,7 @@ class Shadow implements IComparable * * @param int $pValue * - * @return Shadow + * @return $this */ public function setAlpha($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php index a78f4fccaeb..be19abbd27f 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php @@ -172,7 +172,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setOddHeader($pValue) { @@ -196,7 +196,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setOddFooter($pValue) { @@ -220,7 +220,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setEvenHeader($pValue) { @@ -244,7 +244,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setEvenFooter($pValue) { @@ -268,7 +268,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setFirstHeader($pValue) { @@ -292,7 +292,7 @@ class HeaderFooter * * @param string $pValue * - * @return HeaderFooter + * @return $this */ public function setFirstFooter($pValue) { @@ -316,7 +316,7 @@ class HeaderFooter * * @param bool $pValue * - * @return HeaderFooter + * @return $this */ public function setDifferentOddEven($pValue) { @@ -340,7 +340,7 @@ class HeaderFooter * * @param bool $pValue * - * @return HeaderFooter + * @return $this */ public function setDifferentFirst($pValue) { @@ -364,7 +364,7 @@ class HeaderFooter * * @param bool $pValue * - * @return HeaderFooter + * @return $this */ public function setScaleWithDocument($pValue) { @@ -388,7 +388,7 @@ class HeaderFooter * * @param bool $pValue * - * @return HeaderFooter + * @return $this */ public function setAlignWithMargins($pValue) { @@ -403,7 +403,7 @@ class HeaderFooter * @param HeaderFooterDrawing $image * @param string $location * - * @return HeaderFooter + * @return $this */ public function addImage(HeaderFooterDrawing $image, $location = self::IMAGE_HEADER_LEFT) { @@ -417,7 +417,7 @@ class HeaderFooter * * @param string $location * - * @return HeaderFooter + * @return $this */ public function removeImage($location = self::IMAGE_HEADER_LEFT) { @@ -433,7 +433,7 @@ class HeaderFooter * * @param HeaderFooterDrawing[] $images * - * @return HeaderFooter + * @return $this */ public function setImages(array $images) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php index 6012e93e6ea..f0935585dac 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php @@ -74,7 +74,7 @@ class MemoryDrawing extends BaseDrawing * * @param resource $value * - * @return MemoryDrawing + * @return $this */ public function setImageResource($value) { @@ -104,7 +104,7 @@ class MemoryDrawing extends BaseDrawing * * @param string $value see self::RENDERING_* * - * @return MemoryDrawing + * @return $this */ public function setRenderingFunction($value) { @@ -128,7 +128,7 @@ class MemoryDrawing extends BaseDrawing * * @param string $value see self::MIMETYPE_* * - * @return MemoryDrawing + * @return $this */ public function setMimeType($value) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php index eb44a1094c5..9ebfb6488bc 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php @@ -68,7 +68,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setLeft($pValue) { @@ -92,7 +92,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setRight($pValue) { @@ -116,7 +116,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setTop($pValue) { @@ -140,7 +140,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setBottom($pValue) { @@ -164,7 +164,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setHeader($pValue) { @@ -188,7 +188,7 @@ class PageMargins * * @param float $pValue * - * @return PageMargins + * @return $this */ public function setFooter($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php index ab007f61d54..38a09736395 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php @@ -180,7 +180,7 @@ class PageSetup * Print scaling. Valid values range from 10 to 400 * This setting is overridden when fitToWidth and/or fitToHeight are in use * - * @var int? + * @var null|int */ private $scale = 100; @@ -196,7 +196,7 @@ class PageSetup * Fit To Height * Number of vertical pages to fit on. * - * @var int? + * @var null|int */ private $fitToHeight = 1; @@ -204,7 +204,7 @@ class PageSetup * Fit To Width * Number of horizontal pages to fit on. * - * @var int? + * @var null|int */ private $fitToWidth = 1; @@ -272,7 +272,7 @@ class PageSetup * * @param int $pValue see self::PAPERSIZE_* * - * @return PageSetup + * @return $this */ public function setPaperSize($pValue) { @@ -296,7 +296,7 @@ class PageSetup * * @param string $pValue see self::ORIENTATION_* * - * @return PageSetup + * @return $this */ public function setOrientation($pValue) { @@ -308,7 +308,7 @@ class PageSetup /** * Get Scale. * - * @return int? + * @return null|int */ public function getScale() { @@ -325,7 +325,7 @@ class PageSetup * * @throws PhpSpreadsheetException * - * @return PageSetup + * @return $this */ public function setScale($pValue, $pUpdate = true) { @@ -358,7 +358,7 @@ class PageSetup * * @param bool $pValue * - * @return PageSetup + * @return $this */ public function setFitToPage($pValue) { @@ -370,7 +370,7 @@ class PageSetup /** * Get Fit To Height. * - * @return int? + * @return null|int */ public function getFitToHeight() { @@ -383,7 +383,7 @@ class PageSetup * @param null|int $pValue * @param bool $pUpdate Update fitToPage so it applies rather than scaling * - * @return PageSetup + * @return $this */ public function setFitToHeight($pValue, $pUpdate = true) { @@ -398,7 +398,7 @@ class PageSetup /** * Get Fit To Width. * - * @return int? + * @return null|int */ public function getFitToWidth() { @@ -411,7 +411,7 @@ class PageSetup * @param null|int $pValue * @param bool $pUpdate Update fitToPage so it applies rather than scaling * - * @return PageSetup + * @return $this */ public function setFitToWidth($pValue, $pUpdate = true) { @@ -454,7 +454,7 @@ class PageSetup * * @param array $pValue Containing start column and end column, empty array if option unset * - * @return PageSetup + * @return $this */ public function setColumnsToRepeatAtLeft(array $pValue) { @@ -469,7 +469,7 @@ class PageSetup * @param string $pStart eg: 'A' * @param string $pEnd eg: 'B' * - * @return PageSetup + * @return $this */ public function setColumnsToRepeatAtLeftByStartAndEnd($pStart, $pEnd) { @@ -509,7 +509,7 @@ class PageSetup * * @param array $pValue Containing start column and end column, empty array if option unset * - * @return PageSetup + * @return $this */ public function setRowsToRepeatAtTop(array $pValue) { @@ -524,7 +524,7 @@ class PageSetup * @param int $pStart eg: 1 * @param int $pEnd eg: 1 * - * @return PageSetup + * @return $this */ public function setRowsToRepeatAtTopByStartAndEnd($pStart, $pEnd) { @@ -548,7 +548,7 @@ class PageSetup * * @param bool $value * - * @return PageSetup + * @return $this */ public function setHorizontalCentered($value) { @@ -572,7 +572,7 @@ class PageSetup * * @param bool $value * - * @return PageSetup + * @return $this */ public function setVerticalCentered($value) { @@ -634,7 +634,7 @@ class PageSetup * Otherwise, the range identified by the value of $index will be removed from the series * Print areas are numbered from 1 * - * @return PageSetup + * @return $this */ public function clearPrintArea($index = 0) { @@ -671,7 +671,7 @@ class PageSetup * * @throws PhpSpreadsheetException * - * @return PageSetup + * @return $this */ public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { @@ -732,7 +732,7 @@ class PageSetup * * @throws PhpSpreadsheetException * - * @return PageSetup + * @return $this */ public function addPrintArea($value, $index = -1) { @@ -762,7 +762,7 @@ class PageSetup * * @throws PhpSpreadsheetException * - * @return PageSetup + * @return $this */ public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { @@ -789,7 +789,7 @@ class PageSetup * * @throws PhpSpreadsheetException * - * @return PageSetup + * @return $this */ public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1) { @@ -815,7 +815,7 @@ class PageSetup * * @param int $value * - * @return PageSetup + * @return $this */ public function setFirstPageNumber($value) { @@ -827,7 +827,7 @@ class PageSetup /** * Reset first page number. * - * @return PageSetup + * @return $this */ public function resetFirstPageNumber() { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php index 1815f45bf07..2fd3e9195e5 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php @@ -172,7 +172,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setSheet($pValue) { @@ -196,7 +196,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setObjects($pValue) { @@ -220,7 +220,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setScenarios($pValue) { @@ -244,7 +244,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setFormatCells($pValue) { @@ -268,7 +268,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setFormatColumns($pValue) { @@ -292,7 +292,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setFormatRows($pValue) { @@ -316,7 +316,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setInsertColumns($pValue) { @@ -340,7 +340,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setInsertRows($pValue) { @@ -364,7 +364,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setInsertHyperlinks($pValue) { @@ -388,7 +388,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setDeleteColumns($pValue) { @@ -412,7 +412,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setDeleteRows($pValue) { @@ -436,7 +436,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setSelectLockedCells($pValue) { @@ -460,7 +460,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setSort($pValue) { @@ -484,7 +484,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setAutoFilter($pValue) { @@ -508,7 +508,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setPivotTables($pValue) { @@ -532,7 +532,7 @@ class Protection * * @param bool $pValue * - * @return Protection + * @return $this */ public function setSelectUnlockedCells($pValue) { @@ -557,7 +557,7 @@ class Protection * @param string $pValue * @param bool $pAlreadyHashed If the password has already been hashed, set this to true * - * @return Protection + * @return $this */ public function setPassword($pValue, $pAlreadyHashed = false) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php index 8510d402a35..9746d6403d1 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php @@ -59,7 +59,7 @@ class RowCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return RowCellIterator + * @return $this */ public function resetStart($startColumn = 'A') { @@ -77,7 +77,7 @@ class RowCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return RowCellIterator + * @return $this */ public function resetEnd($endColumn = null) { @@ -95,7 +95,7 @@ class RowCellIterator extends CellIterator * * @throws PhpSpreadsheetException * - * @return RowCellIterator + * @return $this */ public function seek($column = 'A') { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php index e4346404d23..c4a87bdb558 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php @@ -56,7 +56,7 @@ class RowDimension extends Dimension * * @param int $pValue * - * @return RowDimension + * @return $this */ public function setRowIndex($pValue) { @@ -80,7 +80,7 @@ class RowDimension extends Dimension * * @param float $pValue * - * @return RowDimension + * @return $this */ public function setRowHeight($pValue) { @@ -104,7 +104,7 @@ class RowDimension extends Dimension * * @param bool $pValue * - * @return RowDimension + * @return $this */ public function setZeroHeight($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php index 433cea6a12a..3b9d0e26537 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php @@ -64,7 +64,7 @@ class RowIterator implements \Iterator * * @throws PhpSpreadsheetException * - * @return RowIterator + * @return $this */ public function resetStart($startRow = 1) { @@ -86,7 +86,7 @@ class RowIterator implements \Iterator * * @param int $endRow The row number at which to stop iterating * - * @return RowIterator + * @return $this */ public function resetEnd($endRow = null) { @@ -102,7 +102,7 @@ class RowIterator implements \Iterator * * @throws PhpSpreadsheetException * - * @return RowIterator + * @return $this */ public function seek($row = 1) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php index 172823245e0..fa85bd27d68 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php @@ -35,6 +35,16 @@ class SheetView */ private $zoomScaleNormal = 100; + /** + * ShowZeros. + * + * If true, "null" values from a calculation will be shown as "0". This is the default Excel behaviour and can be changed + * with the advanced worksheet option "Show a zero in cells that have zero value" + * + * @var bool + */ + private $showZeros = true; + /** * View. * @@ -69,7 +79,7 @@ class SheetView * * @throws PhpSpreadsheetException * - * @return SheetView + * @return $this */ public function setZoomScale($pValue) { @@ -102,7 +112,7 @@ class SheetView * * @throws PhpSpreadsheetException * - * @return SheetView + * @return $this */ public function setZoomScaleNormal($pValue) { @@ -115,6 +125,24 @@ class SheetView return $this; } + /** + * Set ShowZeroes setting. + * + * @param bool $pValue + */ + public function setShowZeros($pValue) + { + $this->showZeros = $pValue; + } + + /** + * @return bool + */ + public function getShowZeros() + { + return $this->showZeros; + } + /** * Get View. * @@ -137,7 +165,7 @@ class SheetView * * @throws PhpSpreadsheetException * - * @return SheetView + * @return $this */ public function setView($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php index 1e525a3fecb..9a3f96471d8 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php @@ -647,7 +647,7 @@ class Worksheet implements IComparable /** * Refresh column dimensions. * - * @return Worksheet + * @return $this */ public function refreshColumnDimensions() { @@ -666,7 +666,7 @@ class Worksheet implements IComparable /** * Refresh row dimensions. * - * @return Worksheet + * @return $this */ public function refreshRowDimensions() { @@ -690,7 +690,7 @@ class Worksheet implements IComparable public function calculateWorksheetDimension() { // Return - return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); + return 'A1:' . $this->getHighestColumn() . $this->getHighestRow(); } /** @@ -701,13 +701,13 @@ class Worksheet implements IComparable public function calculateWorksheetDataDimension() { // Return - return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); + return 'A1:' . $this->getHighestDataColumn() . $this->getHighestDataRow(); } /** * Calculate widths for auto-size columns. * - * @return Worksheet; + * @return $this */ public function calculateColumnWidths() { @@ -797,7 +797,7 @@ class Worksheet implements IComparable * * @param Spreadsheet $parent * - * @return Worksheet + * @return $this */ public function rebindParent(Spreadsheet $parent) { @@ -838,7 +838,7 @@ class Worksheet implements IComparable * @param bool $validate False to skip validation of new title. WARNING: This should only be set * at parse time (by Readers), where titles can be assumed to be valid. * - * @return Worksheet + * @return $this */ public function setTitle($pValue, $updateFormulaCellReferences = true, $validate = true) { @@ -913,7 +913,7 @@ class Worksheet implements IComparable * * @param string $value Sheet state (visible, hidden, veryHidden) * - * @return Worksheet + * @return $this */ public function setSheetState($value) { @@ -937,7 +937,7 @@ class Worksheet implements IComparable * * @param PageSetup $pValue * - * @return Worksheet + * @return $this */ public function setPageSetup(PageSetup $pValue) { @@ -961,7 +961,7 @@ class Worksheet implements IComparable * * @param PageMargins $pValue * - * @return Worksheet + * @return $this */ public function setPageMargins(PageMargins $pValue) { @@ -985,7 +985,7 @@ class Worksheet implements IComparable * * @param HeaderFooter $pValue * - * @return Worksheet + * @return $this */ public function setHeaderFooter(HeaderFooter $pValue) { @@ -1009,7 +1009,7 @@ class Worksheet implements IComparable * * @param SheetView $pValue * - * @return Worksheet + * @return $this */ public function setSheetView(SheetView $pValue) { @@ -1033,7 +1033,7 @@ class Worksheet implements IComparable * * @param Protection $pValue * - * @return Worksheet + * @return $this */ public function setProtection(Protection $pValue) { @@ -1119,7 +1119,7 @@ class Worksheet implements IComparable * @param string $pCoordinate Coordinate of the cell, eg: 'A1' * @param mixed $pValue Value of the cell * - * @return Worksheet + * @return $this */ public function setCellValue($pCoordinate, $pValue) { @@ -1135,7 +1135,7 @@ class Worksheet implements IComparable * @param int $row Numeric row coordinate of the cell * @param mixed $value Value of the cell * - * @return Worksheet + * @return $this */ public function setCellValueByColumnAndRow($columnIndex, $row, $value) { @@ -1151,7 +1151,7 @@ class Worksheet implements IComparable * @param mixed $pValue Value of the cell * @param string $pDataType Explicit data type, see DataType::TYPE_* * - * @return Worksheet + * @return $this */ public function setCellValueExplicit($pCoordinate, $pValue, $pDataType) { @@ -1169,7 +1169,7 @@ class Worksheet implements IComparable * @param mixed $value Value of the cell * @param string $dataType Explicit data type, see DataType::TYPE_* * - * @return Worksheet + * @return $this */ public function setCellValueExplicitByColumnAndRow($columnIndex, $row, $value, $dataType) { @@ -1441,7 +1441,7 @@ class Worksheet implements IComparable $this->parent->setActiveSheetIndex($this->parent->getIndex($this)); // set cell coordinate as active - $this->setSelectedCells(strtoupper($pCellCoordinate)); + $this->setSelectedCells($pCellCoordinate); return $this->parent->getCellXfSupervisor(); } @@ -1480,7 +1480,7 @@ class Worksheet implements IComparable * * @param string $pCoordinate eg: 'A1' * - * @return Worksheet + * @return $this */ public function removeConditionalStyles($pCoordinate) { @@ -1505,7 +1505,7 @@ class Worksheet implements IComparable * @param string $pCoordinate eg: 'A1' * @param $pValue Conditional[] * - * @return Worksheet + * @return $this */ public function setConditionalStyles($pCoordinate, $pValue) { @@ -1545,7 +1545,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function duplicateStyle(Style $pCellStyle, $pRange) { @@ -1561,7 +1561,7 @@ class Worksheet implements IComparable } // Calculate range outer borders - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange . ':' . $pRange); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange . ':' . $pRange); // Make sure we can loop upwards on rows and columns if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { @@ -1590,7 +1590,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function duplicateConditionalStyle(array $pCellStyle, $pRange = '') { @@ -1601,7 +1601,7 @@ class Worksheet implements IComparable } // Calculate range outer borders - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange . ':' . $pRange); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange . ':' . $pRange); // Make sure we can loop upwards on rows and columns if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { @@ -1628,7 +1628,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function setBreak($pCoordinate, $pBreak) { @@ -1657,7 +1657,7 @@ class Worksheet implements IComparable * @param int $row Numeric row coordinate of the cell * @param int $break Break type (type of Worksheet::BREAK_*) * - * @return Worksheet + * @return $this */ public function setBreakByColumnAndRow($columnIndex, $row, $break) { @@ -1681,7 +1681,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function mergeCells($pRange) { @@ -1726,7 +1726,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function mergeCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2) { @@ -1742,7 +1742,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function unmergeCells($pRange) { @@ -1772,7 +1772,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function unmergeCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2) { @@ -1797,7 +1797,7 @@ class Worksheet implements IComparable * * @param array $pValue * - * @return Worksheet + * @return $this */ public function setMergeCells(array $pValue) { @@ -1813,7 +1813,7 @@ class Worksheet implements IComparable * @param string $pPassword Password to unlock the protection * @param bool $pAlreadyHashed If the password has already been hashed, set this to true * - * @return Worksheet + * @return $this */ public function protectCells($pRange, $pPassword, $pAlreadyHashed = false) { @@ -1838,7 +1838,7 @@ class Worksheet implements IComparable * @param string $password Password to unlock the protection * @param bool $alreadyHashed If the password has already been hashed, set this to true * - * @return Worksheet + * @return $this */ public function protectCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2, $password, $alreadyHashed = false) { @@ -1854,7 +1854,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function unprotectCells($pRange) { @@ -1880,7 +1880,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function unprotectCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2) { @@ -1917,7 +1917,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function setAutoFilter($pValue) { @@ -1940,7 +1940,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function setAutoFilterByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2) { @@ -1954,7 +1954,7 @@ class Worksheet implements IComparable /** * Remove autofilter. * - * @return Worksheet + * @return $this */ public function removeAutoFilter() { @@ -1987,7 +1987,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function freezePane($cell, $topLeftCell = null) { @@ -2012,7 +2012,7 @@ class Worksheet implements IComparable * @param int $columnIndex Numeric column coordinate of the cell * @param int $row Numeric row coordinate of the cell * - * @return Worksheet + * @return $this */ public function freezePaneByColumnAndRow($columnIndex, $row) { @@ -2022,7 +2022,7 @@ class Worksheet implements IComparable /** * Unfreeze Pane. * - * @return Worksheet + * @return $this */ public function unfreezePane() { @@ -2047,7 +2047,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function insertNewRowBefore($pBefore, $pNumRows = 1) { @@ -2069,7 +2069,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function insertNewColumnBefore($pBefore, $pNumCols = 1) { @@ -2091,7 +2091,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function insertNewColumnBeforeByIndex($beforeColumnIndex, $pNumCols = 1) { @@ -2110,22 +2110,31 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function removeRow($pRow, $pNumRows = 1) { - if ($pRow >= 1) { - $highestRow = $this->getHighestDataRow(); - $objReferenceHelper = ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); - for ($r = 0; $r < $pNumRows; ++$r) { - $this->getCellCollection()->removeRow($highestRow); - --$highestRow; - } - } else { + if ($pRow < 1) { throw new Exception('Rows to be deleted should at least start from row 1.'); } + $highestRow = $this->getHighestDataRow(); + $removedRowsCounter = 0; + + for ($r = 0; $r < $pNumRows; ++$r) { + if ($pRow + $r <= $highestRow) { + $this->getCellCollection()->removeRow($pRow + $r); + ++$removedRowsCounter; + } + } + + $objReferenceHelper = ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); + for ($r = 0; $r < $removedRowsCounter; ++$r) { + $this->getCellCollection()->removeRow($highestRow); + --$highestRow; + } + return $this; } @@ -2137,23 +2146,35 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function removeColumn($pColumn, $pNumCols = 1) { - if (!is_numeric($pColumn)) { - $highestColumn = $this->getHighestDataColumn(); - $pColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($pColumn) + $pNumCols); - $objReferenceHelper = ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); - for ($c = 0; $c < $pNumCols; ++$c) { - $this->getCellCollection()->removeColumn($highestColumn); - $highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1); - } - } else { + if (is_numeric($pColumn)) { throw new Exception('Column references should not be numeric.'); } + $highestColumn = $this->getHighestDataColumn(); + $highestColumnIndex = Coordinate::columnIndexFromString($highestColumn); + $pColumnIndex = Coordinate::columnIndexFromString($pColumn); + + if ($pColumnIndex > $highestColumnIndex) { + return $this; + } + + $pColumn = Coordinate::stringFromColumnIndex($pColumnIndex + $pNumCols); + $objReferenceHelper = ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); + + $maxPossibleColumnsToBeRemoved = $highestColumnIndex - $pColumnIndex + 1; + + for ($c = 0, $n = min($maxPossibleColumnsToBeRemoved, $pNumCols); $c < $n; ++$c) { + $this->getCellCollection()->removeColumn($highestColumn); + $highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1); + } + + $this->garbageCollect(); + return $this; } @@ -2165,7 +2186,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function removeColumnByIndex($columnIndex, $numColumns = 1) { @@ -2191,7 +2212,7 @@ class Worksheet implements IComparable * * @param bool $pValue Show gridlines (true/false) * - * @return Worksheet + * @return $this */ public function setShowGridlines($pValue) { @@ -2215,7 +2236,7 @@ class Worksheet implements IComparable * * @param bool $pValue Print gridlines (true/false) * - * @return Worksheet + * @return $this */ public function setPrintGridlines($pValue) { @@ -2239,7 +2260,7 @@ class Worksheet implements IComparable * * @param bool $pValue Show row and column headers (true/false) * - * @return Worksheet + * @return $this */ public function setShowRowColHeaders($pValue) { @@ -2263,7 +2284,7 @@ class Worksheet implements IComparable * * @param bool $pValue Show summary below (true/false) * - * @return Worksheet + * @return $this */ public function setShowSummaryBelow($pValue) { @@ -2287,7 +2308,7 @@ class Worksheet implements IComparable * * @param bool $pValue Show summary right (true/false) * - * @return Worksheet + * @return $this */ public function setShowSummaryRight($pValue) { @@ -2311,7 +2332,7 @@ class Worksheet implements IComparable * * @param Comment[] $pValue * - * @return Worksheet + * @return $this */ public function setComments(array $pValue) { @@ -2392,7 +2413,7 @@ class Worksheet implements IComparable * * @param string $pCoordinate Cell (i.e. A1) * - * @return Worksheet + * @return $this */ public function setSelectedCell($pCoordinate) { @@ -2404,7 +2425,7 @@ class Worksheet implements IComparable * * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' * - * @return Worksheet + * @return $this */ public function setSelectedCells($pCoordinate) { @@ -2424,7 +2445,7 @@ class Worksheet implements IComparable $pCoordinate = preg_replace('/^(\d+):(\d+)$/', 'A${1}:XFD${2}', $pCoordinate); if (Coordinate::coordinateIsRange($pCoordinate)) { - list($first) = Coordinate::splitRange($pCoordinate); + [$first] = Coordinate::splitRange($pCoordinate); $this->activeCell = $first[0]; } else { $this->activeCell = $pCoordinate; @@ -2442,7 +2463,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function setSelectedCellByColumnAndRow($columnIndex, $row) { @@ -2464,7 +2485,7 @@ class Worksheet implements IComparable * * @param bool $value Right-to-left true/false * - * @return Worksheet + * @return $this */ public function setRightToLeft($value) { @@ -2483,7 +2504,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function fromArray(array $source, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { @@ -2493,7 +2514,7 @@ class Worksheet implements IComparable } // start coordinate - list($startColumn, $startRow) = Coordinate::coordinateFromString($startCell); + [$startColumn, $startRow] = Coordinate::coordinateFromString($startCell); // Loop through $source foreach ($source as $rowData) { @@ -2535,7 +2556,7 @@ class Worksheet implements IComparable // Returnvalue $returnValue = []; // Identify the range that we need to extract from the worksheet - list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange); + [$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange); $minCol = Coordinate::stringFromColumnIndex($rangeStart[0]); $minRow = $rangeStart[1]; $maxCol = Coordinate::stringFromColumnIndex($rangeEnd[0]); @@ -2545,11 +2566,11 @@ class Worksheet implements IComparable // Loop through rows $r = -1; for ($row = $minRow; $row <= $maxRow; ++$row) { - $rRef = ($returnCellRef) ? $row : ++$r; + $rRef = $returnCellRef ? $row : ++$r; $c = -1; // Loop through columns in the current row for ($col = $minCol; $col != $maxCol; ++$col) { - $cRef = ($returnCellRef) ? $col : ++$c; + $cRef = $returnCellRef ? $col : ++$c; // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen // so we test and retrieve directly against cellCollection if ($this->cellCollection->has($col . $row)) { @@ -2668,7 +2689,7 @@ class Worksheet implements IComparable /** * Run PhpSpreadsheet garbage collector. * - * @return Worksheet + * @return $this */ public function garbageCollect() { @@ -2768,7 +2789,7 @@ class Worksheet implements IComparable * @param string $pCellCoordinate Cell coordinate to insert hyperlink, eg: 'A1' * @param null|Hyperlink $pHyperlink * - * @return Worksheet + * @return $this */ public function setHyperlink($pCellCoordinate, Hyperlink $pHyperlink = null) { @@ -2829,7 +2850,7 @@ class Worksheet implements IComparable * @param string $pCellCoordinate Cell coordinate to insert data validation, eg: 'A1' * @param null|DataValidation $pDataValidation * - * @return Worksheet + * @return $this */ public function setDataValidation($pCellCoordinate, DataValidation $pDataValidation = null) { @@ -2896,9 +2917,8 @@ class Worksheet implements IComparable $rangeSet = $rangeBoundaries[0][0] . $rangeBoundaries[0][1] . ':' . $rangeBoundaries[1][0] . $rangeBoundaries[1][1]; } unset($rangeSet); - $stRange = implode(' ', $rangeBlocks); - return $stRange; + return implode(' ', $rangeBlocks); } /** @@ -2918,7 +2938,7 @@ class Worksheet implements IComparable /** * Reset tab color. * - * @return Worksheet + * @return $this */ public function resetTabColor() { @@ -2941,13 +2961,11 @@ class Worksheet implements IComparable /** * Copy worksheet (!= clone!). * - * @return Worksheet + * @return static */ public function copy() { - $copied = clone $this; - - return $copied; + return clone $this; } /** @@ -2994,7 +3012,7 @@ class Worksheet implements IComparable * * @throws Exception * - * @return Worksheet + * @return $this */ public function setCodeName($pValue, $validate = true) { @@ -3034,7 +3052,7 @@ class Worksheet implements IComparable } } - $pValue = $pValue . '_' . $i; // ok, we have a valid name + $pValue .= '_' . $i; // ok, we have a valid name } } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php index ae38ab73218..1166bd25b18 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php @@ -147,7 +147,7 @@ class Csv extends BaseWriter * * @param string $pValue Delimiter, defaults to ',' * - * @return CSV + * @return $this */ public function setDelimiter($pValue) { @@ -171,7 +171,7 @@ class Csv extends BaseWriter * * @param string $pValue Enclosure, defaults to " * - * @return CSV + * @return $this */ public function setEnclosure($pValue) { @@ -198,7 +198,7 @@ class Csv extends BaseWriter * * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) * - * @return CSV + * @return $this */ public function setLineEnding($pValue) { @@ -222,7 +222,7 @@ class Csv extends BaseWriter * * @param bool $pValue Use UTF-8 byte-order mark? Defaults to false * - * @return CSV + * @return $this */ public function setUseBOM($pValue) { @@ -246,7 +246,7 @@ class Csv extends BaseWriter * * @param bool $pValue Use separator line? Defaults to false * - * @return CSV + * @return $this */ public function setIncludeSeparatorLine($pValue) { @@ -271,7 +271,7 @@ class Csv extends BaseWriter * @param bool $pValue Set the file to be written as a fully Excel compatible csv file * Note that this overrides other settings such as useBOM, enclosure and delimiter * - * @return CSV + * @return $this */ public function setExcelCompatibility($pValue) { @@ -295,7 +295,7 @@ class Csv extends BaseWriter * * @param int $pValue Sheet index * - * @return CSV + * @return $this */ public function setSheetIndex($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php index 8cd026d3190..37d68e912e2 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php @@ -62,6 +62,13 @@ class Html extends BaseWriter */ private $useInlineCss = false; + /** + * Use embedded CSS? + * + * @var bool + */ + private $useEmbeddedCSS = true; + /** * Array of CSS styles. * @@ -290,7 +297,7 @@ class Html extends BaseWriter * * @param int $pValue Sheet index * - * @return HTML + * @return $this */ public function setSheetIndex($pValue) { @@ -314,7 +321,7 @@ class Html extends BaseWriter * * @param bool $pValue Flag indicating whether the sheet navigation block should be generated or not * - * @return HTML + * @return $this */ public function setGenerateSheetNavigationBlock($pValue) { @@ -325,6 +332,8 @@ class Html extends BaseWriter /** * Write all sheets (resets sheetIndex to NULL). + * + * @return $this */ public function writeAllSheets() { @@ -643,7 +652,10 @@ class Html extends BaseWriter } else { $imageDetails = getimagesize($filename); if ($fp = fopen($filename, 'rb', 0)) { - $picture = fread($fp, filesize($filename)); + $picture = ''; + while (!feof($fp)) { + $picture .= fread($fp, 1024); + } fclose($fp); // base64 encode the binary data, then break it // into chunks according to RFC 2045 semantics @@ -888,8 +900,8 @@ class Html extends BaseWriter $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; if ($columnDimension->getVisible() === false) { - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; - $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7 + $css['table.sheet' . $sheetIndex . ' .column' . $column]['visibility'] = 'collapse'; + $css['table.sheet' . $sheetIndex . ' .column' . $column]['display'] = 'none'; // target IE6+7 } } } @@ -950,15 +962,12 @@ class Html extends BaseWriter private function createCSSStyle(Style $pStyle) { // Create CSS - $css = array_merge( + return array_merge( $this->createCSSStyleAlignment($pStyle->getAlignment()), $this->createCSSStyleBorders($pStyle->getBorders()), $this->createCSSStyleFont($pStyle->getFont()), $this->createCSSStyleFill($pStyle->getFill()) ); - - // Return - return $css; } /** @@ -1051,9 +1060,8 @@ class Html extends BaseWriter { // Create CSS - add !important to non-none border styles for merged cells $borderStyle = $this->mapBorderStyle($pStyle->getBorderStyle()); - $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); - return $css; + return $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); } /** @@ -1102,7 +1110,9 @@ class Html extends BaseWriter // Construct HTML $html = ''; - $html .= $this->setMargins($pSheet); + if ($this->useEmbeddedCSS) { + $html .= $this->setMargins($pSheet); + } if (!$this->useInlineCss) { $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : ''; @@ -1141,9 +1151,7 @@ class Html extends BaseWriter */ private function generateTableFooter() { - $html = ' ' . PHP_EOL; - - return $html; + return ' ' . PHP_EOL; } /** @@ -1432,7 +1440,7 @@ class Html extends BaseWriter * * @param string $pValue * - * @return HTML + * @return $this */ public function setImagesRoot($pValue) { @@ -1456,7 +1464,7 @@ class Html extends BaseWriter * * @param bool $pValue * - * @return HTML + * @return $this */ public function setEmbedImages($pValue) { @@ -1480,7 +1488,7 @@ class Html extends BaseWriter * * @param bool $pValue * - * @return HTML + * @return $this */ public function setUseInlineCss($pValue) { @@ -1489,6 +1497,30 @@ class Html extends BaseWriter return $this; } + /** + * Get use embedded CSS? + * + * @return bool + */ + public function getUseEmbeddedCSS() + { + return $this->useEmbeddedCSS; + } + + /** + * Set use embedded CSS? + * + * @param bool $pValue + * + * @return $this + */ + public function setUseEmbeddedCSS($pValue) + { + $this->useEmbeddedCSS = $pValue; + + return $this; + } + /** * Add color to formatted string as inline style. * @@ -1538,14 +1570,14 @@ class Html extends BaseWriter // loop through all Excel merged cells foreach ($sheet->getMergeCells() as $cells) { - list($cells) = Coordinate::splitRange($cells); + [$cells] = Coordinate::splitRange($cells); $first = $cells[0]; $last = $cells[1]; - list($fc, $fr) = Coordinate::coordinateFromString($first); + [$fc, $fr] = Coordinate::coordinateFromString($first); $fc = Coordinate::columnIndexFromString($fc) - 1; - list($lc, $lr) = Coordinate::coordinateFromString($last); + [$lc, $lr] = Coordinate::coordinateFromString($last); $lc = Coordinate::columnIndexFromString($lc) - 1; // loop through the individual cells in the individual merge diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php index 83fc2931db5..43659fa08ef 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php @@ -167,7 +167,7 @@ class Ods extends BaseWriter * * @param Spreadsheet $spreadsheet PhpSpreadsheet object * - * @return self + * @return $this */ public function setSpreadsheet(Spreadsheet $spreadsheet) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php index 11de0fd3733..dea5100f595 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php @@ -314,7 +314,7 @@ class Content extends WriterPart } if ($size = $font->getSize()) { - $writer->writeAttribute('fo:font-size', sprintf('%.1fpt', $size)); + $writer->writeAttribute('fo:font-size', sprintf('%.1Fpt', $size)); } if ($font->getUnderline() && $font->getUnderline() != Font::UNDERLINE_NONE) { @@ -383,7 +383,7 @@ class Content extends WriterPart } $mergeRange = Coordinate::splitRange($cell->getMergeRange()); - list($startCell, $endCell) = $mergeRange[0]; + [$startCell, $endCell] = $mergeRange[0]; $start = Coordinate::coordinateFromString($startCell); $end = Coordinate::coordinateFromString($endCell); $columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php index b80083ae466..d91845603a1 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php @@ -150,7 +150,7 @@ abstract class Pdf extends Html * * @param string $fontName * - * @return Pdf + * @return $this */ public function setFont($fontName) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php index 6dff1342aed..6932eb1ac47 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php @@ -459,7 +459,7 @@ class Xls extends BaseWriter if ($drawing instanceof Drawing) { $filename = $drawing->getPath(); - list($imagesx, $imagesy, $imageFormat) = getimagesize($filename); + [$imagesx, $imagesy, $imageFormat] = getimagesize($filename); switch ($imageFormat) { case 1: // GIF, not supported by BIFF8, we convert to PNG diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php index 1dcef8072fc..1ee2e904714 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php @@ -420,7 +420,7 @@ class Escher $recType = 0xF010; // start coordinates - list($column, $row) = Coordinate::coordinateFromString($this->object->getStartCoordinates()); + [$column, $row] = Coordinate::coordinateFromString($this->object->getStartCoordinates()); $c1 = Coordinate::columnIndexFromString($column) - 1; $r1 = $row - 1; @@ -431,7 +431,7 @@ class Escher $startOffsetY = $this->object->getStartOffsetY(); // end coordinates - list($column, $row) = Coordinate::coordinateFromString($this->object->getEndCoordinates()); + [$column, $row] = Coordinate::coordinateFromString($this->object->getEndCoordinates()); $c2 = Coordinate::columnIndexFromString($column) - 1; $r2 = $row - 1; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php index 6049e32878b..5982062845c 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php @@ -608,15 +608,15 @@ class Parser // TODO: possible class value 0,1,2 check Formula.pm // Split the range into 2 cell refs if (preg_match('/^(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)\:(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)$/', $range)) { - list($cell1, $cell2) = explode(':', $range); + [$cell1, $cell2] = explode(':', $range); } else { // TODO: use real error codes throw new WriterException('Unknown range separator'); } // Convert the cell references - list($row1, $col1) = $this->cellToPackedRowcol($cell1); - list($row2, $col2) = $this->cellToPackedRowcol($cell2); + [$row1, $col1] = $this->cellToPackedRowcol($cell1); + [$row2, $col2] = $this->cellToPackedRowcol($cell2); // The ptg value depends on the class of the ptg. if ($class == 0) { @@ -644,20 +644,20 @@ class Parser private function convertRange3d($token) { // Split the ref at the ! symbol - list($ext_ref, $range) = PhpspreadsheetWorksheet::extractSheetTitle($token, true); + [$ext_ref, $range] = PhpspreadsheetWorksheet::extractSheetTitle($token, true); // Convert the external reference part (different for BIFF8) $ext_ref = $this->getRefIndex($ext_ref); // Split the range into 2 cell refs - list($cell1, $cell2) = explode(':', $range); + [$cell1, $cell2] = explode(':', $range); // Convert the cell references if (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\\d+)$/', $cell1)) { - list($row1, $col1) = $this->cellToPackedRowcol($cell1); - list($row2, $col2) = $this->cellToPackedRowcol($cell2); + [$row1, $col1] = $this->cellToPackedRowcol($cell1); + [$row2, $col2] = $this->cellToPackedRowcol($cell2); } else { // It's a rows range (like 26:27) - list($row1, $col1, $row2, $col2) = $this->rangeToPackedRange($cell1 . ':' . $cell2); + [$row1, $col1, $row2, $col2] = $this->rangeToPackedRange($cell1 . ':' . $cell2); } // The ptg value depends on the class of the ptg. @@ -677,7 +677,7 @@ class Parser { // Convert the cell reference $cell_array = $this->cellToPackedRowcol($cell); - list($row, $col) = $cell_array; + [$row, $col] = $cell_array; // The ptg value depends on the class of the ptg. $ptgRef = pack('C', $this->ptg['ptgRefA']); @@ -696,13 +696,13 @@ class Parser private function convertRef3d($cell) { // Split the ref at the ! symbol - list($ext_ref, $cell) = PhpspreadsheetWorksheet::extractSheetTitle($cell, true); + [$ext_ref, $cell] = PhpspreadsheetWorksheet::extractSheetTitle($cell, true); // Convert the external reference part (different for BIFF8) $ext_ref = $this->getRefIndex($ext_ref); // Convert the cell reference part - list($row, $col) = $this->cellToPackedRowcol($cell); + [$row, $col] = $this->cellToPackedRowcol($cell); // The ptg value depends on the class of the ptg. $ptgRef = pack('C', $this->ptg['ptgRef3dA']); @@ -756,7 +756,7 @@ class Parser // Check if there is a sheet range eg., Sheet1:Sheet2. if (preg_match('/:/', $ext_ref)) { - list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + [$sheet_name1, $sheet_name2] = explode(':', $ext_ref); $sheet1 = $this->getSheetIndex($sheet_name1); if ($sheet1 == -1) { @@ -769,7 +769,7 @@ class Parser // Reverse max and min sheet numbers if necessary if ($sheet1 > $sheet2) { - list($sheet1, $sheet2) = [$sheet2, $sheet1]; + [$sheet1, $sheet2] = [$sheet2, $sheet1]; } } else { // Single sheet name only. $sheet1 = $this->getSheetIndex($ext_ref); @@ -843,7 +843,7 @@ class Parser private function cellToPackedRowcol($cell) { $cell = strtoupper($cell); - list($row, $col, $row_rel, $col_rel) = $this->cellToRowcol($cell); + [$row, $col, $row_rel, $col_rel] = $this->cellToRowcol($cell); if ($col >= 256) { throw new WriterException("Column in: $cell greater than 255"); } @@ -1077,8 +1077,8 @@ class Parser public function parse($formula) { $this->currentCharacter = 0; - $this->formula = $formula; - $this->lookAhead = isset($formula[1]) ? $formula[1] : ''; + $this->formula = (string) $formula; + $this->lookAhead = $formula[1] ?? ''; $this->advance(); $this->parseTree = $this->condition(); @@ -1161,17 +1161,15 @@ class Parser // catch "-" Term $this->advance(); $result2 = $this->expression(); - $result = $this->createTree('ptgUminus', $result2, ''); - return $result; + return $this->createTree('ptgUminus', $result2, ''); // If it's a positive value } elseif ($this->currentToken == '+') { // catch "+" Term $this->advance(); $result2 = $this->expression(); - $result = $this->createTree('ptgUplus', $result2, ''); - return $result; + return $this->createTree('ptgUplus', $result2, ''); } $result = $this->term(); while (($this->currentToken == '+') or @@ -1205,9 +1203,7 @@ class Parser */ private function parenthesizedExpression() { - $result = $this->createTree('ptgParen', $this->expression(), ''); - - return $result; + return $this->createTree('ptgParen', $this->expression(), ''); } /** @@ -1309,9 +1305,7 @@ class Parser return $result; } elseif (preg_match("/^[A-Z0-9\xc0-\xdc\\.]+$/i", $this->currentToken)) { // if it's a function call - $result = $this->func(); - - return $result; + return $this->func(); } throw new WriterException('Syntax error: ' . $this->currentToken . ', lookahead: ' . $this->lookAhead . ', current char: ' . $this->currentCharacter); @@ -1439,8 +1433,6 @@ class Parser } $converted_tree = $this->convert($tree['value']); - $polish .= $converted_tree; - - return $polish; + return $polish . $converted_tree; } } diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php index db63fa34423..5a6fa61ac9f 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php @@ -281,6 +281,10 @@ class Worksheet extends BIFFwriter { $phpSheet = $this->phpSheet; + // Storing selected cells and active sheet because it changes while parsing cells with formulas. + $selectedCells = $this->phpSheet->getSelectedCells(); + $activeSheetIndex = $this->phpSheet->getParent()->getActiveSheetIndex(); + // Write BOF record $this->storeBof(0x0010); @@ -441,7 +445,29 @@ class Worksheet extends BIFFwriter case DataType::TYPE_FORMULA: $calculatedValue = $this->preCalculateFormulas ? $cell->getCalculatedValue() : null; - $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue); + if (self::WRITE_FORMULA_EXCEPTION == $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue)) { + if ($calculatedValue === null) { + $calculatedValue = $cell->getCalculatedValue(); + } + $calctype = gettype($calculatedValue); + switch ($calctype) { + case 'integer': + case 'double': + $this->writeNumber($row, $column, $calculatedValue, $xfIndex); + + break; + case 'string': + $this->writeString($row, $column, $calculatedValue, $xfIndex); + + break; + case 'boolean': + $this->writeBoolErr($row, $column, $calculatedValue, 0, $xfIndex); + + break; + default: + $this->writeString($row, $column, $cVal, $xfIndex); + } + } break; case DataType::TYPE_BOOL: @@ -459,6 +485,9 @@ class Worksheet extends BIFFwriter // Append $this->writeMsoDrawing(); + // Restoring active sheet. + $this->phpSheet->getParent()->setActiveSheetIndex($activeSheetIndex); + // Write WINDOW2 record $this->writeWindow2(); @@ -471,6 +500,9 @@ class Worksheet extends BIFFwriter $this->writePanes(); } + // Restoring selected cells. + $this->phpSheet->setSelectedCells($selectedCells); + // Write SELECTION record $this->writeSelection(); @@ -479,7 +511,7 @@ class Worksheet extends BIFFwriter // Hyperlinks foreach ($phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { - list($column, $row) = Coordinate::coordinateFromString($coordinate); + [$column, $row] = Coordinate::coordinateFromString($coordinate); $url = $hyperlink->getUrl(); @@ -764,14 +796,20 @@ class Worksheet extends BIFFwriter return 0; } + const WRITE_FORMULA_NORMAL = 0; + const WRITE_FORMULA_ERRORS = -1; + const WRITE_FORMULA_RANGE = -2; + const WRITE_FORMULA_EXCEPTION = -3; + /** * Write a formula to the specified row and column (zero indexed). * The textual representation of the formula is passed to the parser in * Parser.php which returns a packed binary string. * - * Returns 0 : normal termination - * -1 : formula errors (bad formula) - * -2 : row or column out of range + * Returns 0 : WRITE_FORMULA_NORMAL normal termination + * -1 : WRITE_FORMULA_ERRORS formula errors (bad formula) + * -2 : WRITE_FORMULA_RANGE row or column out of range + * -3 : WRITE_FORMULA_EXCEPTION parse raised exception, probably due to definedname * * @param int $row Zero indexed row * @param int $col Zero indexed column @@ -829,7 +867,7 @@ class Worksheet extends BIFFwriter // Error handling $this->writeString($row, $col, 'Unrecognised character for formula', 0); - return -1; + return self::WRITE_FORMULA_ERRORS; } // Parse the formula using the parser in Parser.php @@ -852,9 +890,9 @@ class Worksheet extends BIFFwriter $this->writeStringRecord($stringValue); } - return 0; + return self::WRITE_FORMULA_NORMAL; } catch (PhpSpreadsheetException $e) { - // do nothing + return self::WRITE_FORMULA_EXCEPTION; } } @@ -1222,7 +1260,6 @@ class Worksheet extends BIFFwriter $fFrozenNoSplit = 0; // 0 - bit // no support in PhpSpreadsheet for selected sheet, therefore sheet is only selected if it is the active sheet $fSelected = ($this->phpSheet === $this->phpSheet->getParent()->getActiveSheet()) ? 1 : 0; - $fPaged = 1; // 2 $fPageBreakPreview = $this->phpSheet->getSheetView()->getView() === SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW; $grbit = $fDspFmla; @@ -1234,8 +1271,8 @@ class Worksheet extends BIFFwriter $grbit |= $fArabic << 6; $grbit |= $fDspGuts << 7; $grbit |= $fFrozenNoSplit << 8; - $grbit |= $fSelected << 9; - $grbit |= $fPaged << 10; + $grbit |= $fSelected << 9; // Selected sheets. + $grbit |= $fSelected << 10; // Active sheet. $grbit |= $fPageBreakPreview << 11; $header = pack('vv', $record, $length); @@ -1355,17 +1392,17 @@ class Worksheet extends BIFFwriter $selectedCells = Coordinate::splitRange($this->phpSheet->getSelectedCells()); $selectedCells = $selectedCells[0]; if (count($selectedCells) == 2) { - list($first, $last) = $selectedCells; + [$first, $last] = $selectedCells; } else { $first = $selectedCells[0]; $last = $selectedCells[0]; } - list($colFirst, $rwFirst) = Coordinate::coordinateFromString($first); + [$colFirst, $rwFirst] = Coordinate::coordinateFromString($first); $colFirst = Coordinate::columnIndexFromString($colFirst) - 1; // base 0 column index --$rwFirst; // base 0 row index - list($colLast, $rwLast) = Coordinate::coordinateFromString($last); + [$colLast, $rwLast] = Coordinate::coordinateFromString($last); $colLast = Coordinate::columnIndexFromString($colLast) - 1; // base 0 column index --$rwLast; // base 0 row index @@ -1394,11 +1431,11 @@ class Worksheet extends BIFFwriter // Swap last row/col for first row/col as necessary if ($rwFirst > $rwLast) { - list($rwFirst, $rwLast) = [$rwLast, $rwFirst]; + [$rwFirst, $rwLast] = [$rwLast, $rwFirst]; } if ($colFirst > $colLast) { - list($colFirst, $colLast) = [$colLast, $colFirst]; + [$colFirst, $colLast] = [$colLast, $colFirst]; } $header = pack('vv', $record, $length); @@ -1440,9 +1477,9 @@ class Worksheet extends BIFFwriter // extract the row and column indexes $range = Coordinate::splitRange($mergeCell); - list($first, $last) = $range[0]; - list($firstColumn, $firstRow) = Coordinate::coordinateFromString($first); - list($lastColumn, $lastRow) = Coordinate::coordinateFromString($last); + [$first, $last] = $range[0]; + [$firstColumn, $firstRow] = Coordinate::coordinateFromString($first); + [$lastColumn, $lastRow] = Coordinate::coordinateFromString($last); $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, Coordinate::columnIndexFromString($firstColumn) - 1, Coordinate::columnIndexFromString($lastColumn) - 1); @@ -1589,11 +1626,11 @@ class Worksheet extends BIFFwriter { $panes = []; if ($this->phpSheet->getFreezePane()) { - list($column, $row) = Coordinate::coordinateFromString($this->phpSheet->getFreezePane()); + [$column, $row] = Coordinate::coordinateFromString($this->phpSheet->getFreezePane()); $panes[0] = Coordinate::columnIndexFromString($column) - 1; $panes[1] = $row - 1; - list($leftMostColumn, $topRow) = Coordinate::coordinateFromString($this->phpSheet->getTopLeftCell()); + [$leftMostColumn, $topRow] = Coordinate::coordinateFromString($this->phpSheet->getTopLeftCell()); //Coordinates are zero-based in xls files $panes[2] = $topRow - 1; $panes[3] = Coordinate::columnIndexFromString($leftMostColumn) - 1; @@ -1602,10 +1639,10 @@ class Worksheet extends BIFFwriter return; } - $x = isset($panes[0]) ? $panes[0] : null; - $y = isset($panes[1]) ? $panes[1] : null; - $rwTop = isset($panes[2]) ? $panes[2] : null; - $colLeft = isset($panes[3]) ? $panes[3] : null; + $x = $panes[0] ?? null; + $y = $panes[1] ?? null; + $rwTop = $panes[2] ?? null; + $colLeft = $panes[3] ?? null; if (count($panes) > 4) { // if Active pane was received $pnnAct = $panes[4]; } else { @@ -2215,7 +2252,7 @@ class Worksheet extends BIFFwriter public function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) { $bitmap_array = (is_resource($bitmap) ? $this->processBitmapGd($bitmap) : $this->processBitmap($bitmap)); - list($width, $height, $size, $data) = $bitmap_array; + [$width, $height, $size, $data] = $bitmap_array; // Scale the frame of the image. $width *= $scale_x; diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php index 58897639024..1fa59e51c75 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php @@ -443,7 +443,7 @@ class Xlsx extends BaseWriter * * @param Spreadsheet $spreadsheet PhpSpreadsheet object * - * @return Xlsx + * @return $this */ public function setSpreadsheet(Spreadsheet $spreadsheet) { @@ -547,7 +547,7 @@ class Xlsx extends BaseWriter * * @param bool $pValue Office2003 compatibility? * - * @return Xlsx + * @return $this */ public function setOffice2003Compatibility($pValue) { diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php index 625fd16de21..c9c3e055b28 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php @@ -83,11 +83,11 @@ class Chart extends WriterPart $this->writeLegend($objWriter, $pChart->getLegend()); $objWriter->startElement('c:plotVisOnly'); - $objWriter->writeAttribute('val', 1); + $objWriter->writeAttribute('val', (int) $pChart->getPlotVisibleOnly()); $objWriter->endElement(); $objWriter->startElement('c:dispBlanksAs'); - $objWriter->writeAttribute('val', 'gap'); + $objWriter->writeAttribute('val', $pChart->getDisplayBlanksAs()); $objWriter->endElement(); $objWriter->startElement('c:showDLblsOverMax'); @@ -1136,7 +1136,7 @@ class Chart extends WriterPart $fillColorValues = $plotSeriesValues->getFillColor(); if ($fillColorValues !== null && is_array($fillColorValues)) { foreach ($plotSeriesValues->getDataValues() as $dataKey => $dataValue) { - $this->writePlotSeriesValuesElement($objWriter, $dataKey, (isset($fillColorValues[$dataKey]) ? $fillColorValues[$dataKey] : 'FF9900')); + $this->writePlotSeriesValuesElement($objWriter, $dataKey, ($fillColorValues[$dataKey] ?? 'FF9900')); } } else { $this->writePlotSeriesValuesElement($objWriter); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php index 8b08f31f3f8..a95298afcdd 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php @@ -175,7 +175,7 @@ class Comments extends WriterPart private function writeVMLComment(XMLWriter $objWriter, $pCellReference, Comment $pComment) { // Metadata - list($column, $row) = Coordinate::coordinateFromString($pCellReference); + [$column, $row] = Coordinate::coordinateFromString($pCellReference); $column = Coordinate::columnIndexFromString($column); $id = 1024 + $column + $row; $id = substr($id, 0, 4); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php index b9f8f99b71f..fd936748ad0 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php @@ -339,7 +339,7 @@ class Workbook extends WriterPart $range = Coordinate::splitRange($autoFilterRange); $range = $range[0]; // Strip any worksheet ref so we can make the cell ref absolute - list($ws, $range[0]) = Worksheet::extractSheetTitle($range[0], true); + [$ws, $range[0]] = Worksheet::extractSheetTitle($range[0], true); $range[0] = Coordinate::absoluteCoordinate($range[0]); $range[1] = Coordinate::absoluteCoordinate($range[1]); diff --git a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php index 065eaaf1c9b..1d5a995a8b4 100644 --- a/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php +++ b/htdocs/includes/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php @@ -221,6 +221,11 @@ class Worksheet extends WriterPart $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal()); } + // Show zeros (Excel also writes this attribute only if set to false) + if ($pSheet->getSheetView()->getShowZeros() === false) { + $objWriter->writeAttribute('showZeros', 0); + } + // View Layout Type if ($pSheet->getSheetView()->getView() !== SheetView::SHEETVIEW_NORMAL) { $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView()); @@ -251,14 +256,12 @@ class Worksheet extends WriterPart // Pane $pane = ''; if ($pSheet->getFreezePane()) { - list($xSplit, $ySplit) = Coordinate::coordinateFromString($pSheet->getFreezePane()); + [$xSplit, $ySplit] = Coordinate::coordinateFromString($pSheet->getFreezePane()); $xSplit = Coordinate::columnIndexFromString($xSplit); --$xSplit; --$ySplit; $topLeftCell = $pSheet->getTopLeftCell(); - $activeCell = $topLeftCell; - $sqref = $topLeftCell; // pane $pane = 'topRight'; @@ -522,6 +525,9 @@ class Worksheet extends WriterPart } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSBLANKS) { // formula copied from ms xlsx xml source file $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))=0'); + } elseif ($conditional->getConditionType() == Conditional::CONDITION_NOTCONTAINSBLANKS) { + // formula copied from ms xlsx xml source file + $objWriter->writeElement('formula', 'LEN(TRIM(' . $cellCoordinate . '))>0'); } $objWriter->endElement(); @@ -752,7 +758,7 @@ class Worksheet extends WriterPart $range = Coordinate::splitRange($autoFilterRange); $range = $range[0]; // Strip any worksheet ref - list($ws, $range[0]) = PhpspreadsheetWorksheet::extractSheetTitle($range[0], true); + [$ws, $range[0]] = PhpspreadsheetWorksheet::extractSheetTitle($range[0], true); $range = implode(':', $range); $objWriter->writeAttribute('ref', str_replace('$', '', $range)); @@ -1105,7 +1111,7 @@ class Worksheet extends WriterPart break; case 'f': // Formula $attributes = $pCell->getFormulaAttributes(); - if ($attributes['t'] === 'array') { + if (($attributes['t'] ?? null) === 'array') { $objWriter->startElement('f'); $objWriter->writeAttribute('t', 'array'); $objWriter->writeAttribute('ref', $pCellAddress); @@ -1130,8 +1136,15 @@ class Worksheet extends WriterPart break; case 'n': // Numeric - // force point as decimal separator in case current locale uses comma - $objWriter->writeElement('v', str_replace(',', '.', $cellValue)); + //force a decimal to be written if the type is float + if (is_float($cellValue)) { + // force point as decimal separator in case current locale uses comma + $cellValue = str_replace(',', '.', (string) $cellValue); + if (strpos($cellValue, '.') === false) { + $cellValue = $cellValue . '.0'; + } + } + $objWriter->writeElement('v', $cellValue); break; case 'b': // Boolean diff --git a/htdocs/langs/en_US/multicurrency.lang b/htdocs/langs/en_US/multicurrency.lang index 26313c6bfb9..0345c946ce0 100644 --- a/htdocs/langs/en_US/multicurrency.lang +++ b/htdocs/langs/en_US/multicurrency.lang @@ -36,3 +36,7 @@ Codemulticurrency=currency code UpdateRate=change the rate CancelUpdate=cancel NoEmptyRate=The rate field must not be empty +CurrencyCodeId=Currency ID +CurrencyCode=Currency code +CurrencyUnitPrice=Unit price in foreign currency +CurrencyPrice=Price in foreign currency