commit
						7d58ba8c86
					
				
							
								
								
									
										16
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,16 @@ | ||||
| /tests export-ignore | ||||
| README.md export-ignore | ||||
| *.min.js binary | ||||
| /.gitattributes export-ignore | ||||
| /.github export-ignore | ||||
| /.gitignore export-ignore | ||||
| /.php_cs.dist export-ignore | ||||
| /.sami.php export-ignore | ||||
| /.scrutinizer.yml export-ignore | ||||
| /.travis.yml export-ignore | ||||
| /CHANGELOG.PHPExcel.md export-ignore | ||||
| /bin export-ignore | ||||
| /composer.lock export-ignore | ||||
| /docs export-ignore | ||||
| /mkdocs.yml export-ignore | ||||
| /phpunit.xml.dist export-ignore | ||||
| /samples export-ignore | ||||
| /tests export-ignore | ||||
|  | ||||
							
								
								
									
										119
									
								
								.php_cs.dist
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								.php_cs.dist
									
									
									
									
									
								
							| @ -1,11 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| $finder = PhpCsFixer\Finder::create() | ||||
|     ->exclude(['vendor', 'tests/data/Calculation']) | ||||
|     ->in('samples') | ||||
|     ->in('src') | ||||
|     ->in('tests/PhpSpreadsheetTests') | ||||
|     ; | ||||
|     ->exclude('vendor') | ||||
|     ->in(__DIR__); | ||||
| 
 | ||||
| return PhpCsFixer\Config::create() | ||||
|     ->setRiskyAllowed(true) | ||||
| @ -13,21 +10,27 @@ return PhpCsFixer\Config::create() | ||||
|     ->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer' . preg_replace('~\W~', '-', __DIR__)) | ||||
|     ->setRules([ | ||||
|         'align_multiline_comment' => true, | ||||
|         'array_indentation' => 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_return' => false, // Deprecated | ||||
|         '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 | ||||
|         'class_keyword_remove' => false, // ::class keyword gives us better support in IDE | ||||
|         'combine_consecutive_issets' => true, | ||||
|         'combine_consecutive_unsets' => true, | ||||
|         'combine_nested_dirname' => true, | ||||
|         'comment_to_phpdoc' => true, | ||||
|         'compact_nullable_typehint' => true, | ||||
|         'concat_space' => ['spacing' => 'one'], | ||||
|         'constant_case' => true, | ||||
|         'date_time_immutable' => false, // Break our unit tests | ||||
|         'declare_equal_normalize' => true, | ||||
|         'declare_strict_types' => false, // Too early to adopt strict types | ||||
|         'dir_constant' => true, | ||||
| @ -38,39 +41,57 @@ return PhpCsFixer\Config::create() | ||||
|         'elseif' => true, | ||||
|         'encoding' => true, | ||||
|         'ereg_to_preg' => true, | ||||
|         'error_suppression' => 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_class' => false, // We need non-final classes | ||||
|         'final_internal_class' => true, | ||||
|         'final_public_method_for_abstract_class' => false, // We need non-final methods | ||||
|         'final_static_access' => true, | ||||
|         'fopen_flag_order' => true, | ||||
|         'fopen_flags' => true, | ||||
|         'full_opening_tag' => true, | ||||
|         'fully_qualified_strict_types' => 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, | ||||
|         'general_phpdoc_annotation_remove' => ['access', 'category', 'copyright', 'method', 'throws'], | ||||
|         'global_namespace_import' => true, | ||||
|         'hash_to_slash_comment' => false, // Deprecated | ||||
|         'header_comment' => false, // We don't use common header in all our files | ||||
|         'heredoc_indentation' => false, // Requires PHP >= 7.3 | ||||
|         'heredoc_to_nowdoc' => false, // Not sure about this one | ||||
|         'implode_call' => true, | ||||
|         'include' => true, | ||||
|         'increment_style' => true, | ||||
|         'indentation_type' => true, | ||||
|         'is_null' => ['use_yoda_style' => false], | ||||
|         'linebreak_after_opening_tag' => true, | ||||
|         'is_null' => true, | ||||
|         'line_ending' => true, | ||||
|         'linebreak_after_opening_tag' => true, | ||||
|         'list_syntax' => ['syntax' => 'short'], | ||||
|         'logical_operators' => true, | ||||
|         'lowercase_cast' => true, | ||||
|         'lowercase_constants' => true, | ||||
|         'lowercase_constants' => false, // Deprecated | ||||
|         'lowercase_keywords' => true, | ||||
|         'lowercase_static_reference' => true, | ||||
|         'magic_constant_casing' => true, | ||||
|         'magic_method_casing' => true, | ||||
|         'mb_str_functions' => false, // No, too dangerous to change that | ||||
|         'method_argument_space' => true, | ||||
|         'method_chaining_indentation' => true, | ||||
|         'method_separation' => true, | ||||
|         'method_separation' => false, // Deprecated | ||||
|         'modernize_types_casting' => true, | ||||
|         'multiline_comment_opening_closing' => true, | ||||
|         'multiline_whitespace_before_semicolons' => true, | ||||
|         'native_constant_invocation' => false, // Micro optimization that look messy | ||||
|         '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 | ||||
|         'native_function_invocation' => false, // I suppose this would be best, but I am still unconvinced about the visual aspect of it | ||||
|         'native_function_type_declaration_casing' => true, | ||||
|         'new_with_braces' => true, | ||||
|         'no_alias_functions' => true, | ||||
|         'no_alternative_syntax' => true, | ||||
|         'no_binary_string' => 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 | ||||
| @ -80,16 +101,15 @@ return PhpCsFixer\Config::create() | ||||
|         'no_empty_phpdoc' => true, | ||||
|         'no_empty_statement' => true, | ||||
|         'no_extra_blank_lines' => true, | ||||
|         'no_extra_consecutive_blank_lines' => false, // Deprecated | ||||
|         '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_multiline_whitespace_before_semicolons' => false, // Deprecated | ||||
|         '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, | ||||
| @ -97,29 +117,55 @@ return PhpCsFixer\Config::create() | ||||
|         '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_superfluous_phpdoc_tags' => ['allow_mixed' => true], | ||||
|         '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_trailing_whitespace_in_comment' => true, | ||||
|         'no_unneeded_control_parentheses' => true, | ||||
|         'no_unneeded_curly_braces' => true, | ||||
|         'no_unneeded_final_method' => true, | ||||
|         'no_unreachable_default_argument_value' => true, | ||||
|         'no_unset_cast' => true, | ||||
|         'no_unset_on_property' => 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, | ||||
|         'non_printable_character' => true, | ||||
|         'normalize_index_brace' => true, | ||||
|         'not_operator_with_space' => false, // No we prefer to keep '!' without spaces | ||||
|         'not_operator_with_successor_space' => false, // idem | ||||
|         'nullable_type_declaration_for_default_null_value' => true, | ||||
|         'object_operator_without_whitespace' => true, | ||||
|         'ordered_class_elements' => false, // We prefer to keep some freedom | ||||
|         'ordered_imports' => true, | ||||
|         'ordered_interfaces' => true, | ||||
|         'php_unit_construct' => true, | ||||
|         'php_unit_dedicate_assert' => true, | ||||
|         'php_unit_dedicate_assert_internal_type' => true, | ||||
|         'php_unit_expectation' => true, | ||||
|         'php_unit_fqcn_annotation' => true, | ||||
|         'php_unit_internal_class' => false, // Because tests are excluded from package | ||||
|         'php_unit_method_casing' => true, | ||||
|         'php_unit_mock' => true, | ||||
|         'php_unit_mock_short_will_return' => true, | ||||
|         'php_unit_namespaced' => true, | ||||
|         'php_unit_no_expectation_annotation' => true, | ||||
|         'php_unit_ordered_covers' => true, | ||||
|         'php_unit_set_up_tear_down_visibility' => true, | ||||
|         'php_unit_size_class' => false, // That seems extra work to maintain for little benefits | ||||
|         'php_unit_strict' => false, // We sometime actually need assertEquals | ||||
|         'php_unit_test_annotation' => true, | ||||
|         'php_unit_test_case_static_method_calls' => ['call_type' => 'self'], | ||||
|         'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage | ||||
|         '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_line_span' => false, // Unfortunately our old comments turn even uglier with this | ||||
|         'phpdoc_no_access' => true, | ||||
|         'phpdoc_no_alias_tag' => true, | ||||
|         'phpdoc_no_empty_return' => true, | ||||
| @ -132,43 +178,46 @@ return PhpCsFixer\Config::create() | ||||
|         'phpdoc_single_line_var_spacing' => true, | ||||
|         'phpdoc_summary' => true, | ||||
|         'phpdoc_to_comment' => true, | ||||
|         'phpdoc_to_param_type' => false, // Because experimental, but interesting for one shot use | ||||
|         'phpdoc_to_return_type' => false, // idem | ||||
|         'phpdoc_trim' => true, | ||||
|         'phpdoc_types_order' => true, | ||||
|         'phpdoc_trim_consecutive_blank_line_separation' => true, | ||||
|         'phpdoc_types' => true, | ||||
|         'phpdoc_types_order' => true, | ||||
|         'phpdoc_var_annotation_correct_order' => 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, | ||||
|         'pow_to_exponentiation' => true, | ||||
|         'pre_increment' => false, // Deprecated | ||||
|         'protected_to_private' => true, | ||||
|         'psr0' => true, | ||||
|         'psr4' => true, | ||||
|         'random_api_migration' => false, // This breaks our unit tests | ||||
|         'random_api_migration' => true, | ||||
|         'return_assignment' => false, // Sometimes useful for clarity or debug | ||||
|         'return_type_declaration' => true, | ||||
|         'self_accessor' => true, | ||||
|         'self_static_accessor' => true, | ||||
|         'semicolon_after_instruction' => false, // Buggy in `samples/index.php` | ||||
|         'set_type_to_cast' => true, | ||||
|         'short_scalar_cast' => true, | ||||
|         'silenced_deprecation_error' => true, | ||||
|         'simplified_null_return' => false, // While technically correct we prefer to be explicit when returning null | ||||
|         'silenced_deprecation_error' => false, // Deprecated | ||||
|         'simple_to_complex_string_variable' => false, // Would differ from TypeScript without obvious advantages | ||||
|         'simplified_null_return' => false, // Even if technically correct we prefer to be explicit | ||||
|         '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_line_throw' => false, // I don't see any reason for having a special case for Exception | ||||
|         'single_quote' => true, | ||||
|         'single_trait_insert_per_statement' => true, | ||||
|         'space_after_semicolon' => true, | ||||
|         'standardize_increment' => 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 | ||||
|         'string_line_ending' => true, | ||||
|         'switch_case_semicolon_to_colon' => true, | ||||
|         'switch_case_space' => true, | ||||
|         'ternary_operator_spaces' => true, | ||||
| @ -177,7 +226,7 @@ return PhpCsFixer\Config::create() | ||||
|         'trim_array_spaces' => true, | ||||
|         'unary_operator_spaces' => true, | ||||
|         'visibility_required' => true, | ||||
|         'void_return' => false, // Cannot use that with PHP 5.6 | ||||
|         'void_return' => true, | ||||
|         'whitespace_after_comma_in_array' => true, | ||||
|         'yoda_style' => false, | ||||
|     ]); | ||||
|  | ||||
| @ -41,9 +41,9 @@ jobs: | ||||
|       if: tag is present AND branch = master | ||||
|       php: 7.4 | ||||
|       before_script: | ||||
|       - curl -O https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/phpDocumentor.phar | ||||
|         - curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.0.0-rc/phpDocumentor.phar | ||||
|       script: | ||||
|       - php phpDocumentor.phar --directory src/ --target docs/api | ||||
|         - php phpDocumentor.phar --directory src/ --target docs/api | ||||
|       deploy: | ||||
|         provider: pages | ||||
|         skip-cleanup: true | ||||
|  | ||||
							
								
								
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -7,9 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org). | ||||
| 
 | ||||
| ## [Unreleased] | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| - Support writing to streams in all writers [#1292](https://github.com/PHPOffice/PhpSpreadsheet/issues/1292) | ||||
| - Support CSV files with data wrapping a lot of lines [#1468](https://github.com/PHPOffice/PhpSpreadsheet/pull/1468) | ||||
| 
 | ||||
| ### Fixed | ||||
| 
 | ||||
| - Fix Chart samples by updating chart parameter from 0 to DataSeries::EMPTY_AS_GAP [#1448](https://github.com/PHPOffice/PhpSpreadsheet/pull/1448) | ||||
| - Fix return type in docblock for the Cells::get() [#1398](https://github.com/PHPOffice/PhpSpreadsheet/pull/1398) | ||||
| - Fix RATE, PRICE, XIRR, and XNPV Functions [#1456](https://github.com/PHPOffice/PhpSpreadsheet/pull/1456) | ||||
| - Save Excel 2010+ functions properly in XLSX [#1461](https://github.com/PHPOffice/PhpSpreadsheet/pull/1461) | ||||
| - Several improvements in HTML writer [#1464](https://github.com/PHPOffice/PhpSpreadsheet/pull/1464) | ||||
| 
 | ||||
| ### Changed | ||||
| 
 | ||||
| - Drop support for PHP 7.1, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support | ||||
| - Drop partial migration tool in favor of complete migration via RectorPHP [#1445](https://github.com/PHPOffice/PhpSpreadsheet/issues/1445) | ||||
| - Limit composer package to `src/` [#1424](https://github.com/PHPOffice/PhpSpreadsheet/pull/1424) | ||||
| 
 | ||||
| ## [1.12.0] - 2020-04-27 | ||||
| 
 | ||||
|  | ||||
| @ -22,6 +22,8 @@ PhpSpreadsheet is the next version of PHPExcel. It breaks compatibility to drama | ||||
| 
 | ||||
| Because all efforts have shifted to PhpSpreadsheet, PHPExcel will no longer be maintained. All contributions for PHPExcel, patches and new features, should target PhpSpreadsheet `master` branch. | ||||
| 
 | ||||
| Do you need to migrate? There is [an automated tool](/docs/topics/migration-from-PHPExcel.md) for that. | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| PhpSpreadsheet is licensed under [MIT](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/LICENSE). | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| use PhpOffice\PhpSpreadsheet\Calculation\Calculation; | ||||
| use PhpOffice\PhpSpreadsheet\DocumentGenerator; | ||||
| 
 | ||||
| require_once __DIR__ . '/../src/Bootstrap.php'; | ||||
| require_once 'vendor/autoload.php'; | ||||
| 
 | ||||
| try { | ||||
|     $phpSpreadsheetFunctionsProperty = (new ReflectionClass(Calculation::class))->getProperty('phpSpreadsheetFunctions'); | ||||
| @ -19,6 +19,6 @@ try { | ||||
|         DocumentGenerator::generateFunctionListByName($phpSpreadsheetFunctions) | ||||
|     ); | ||||
| } catch (ReflectionException $e) { | ||||
|     fwrite(STDERR, (string)$e); | ||||
|     fwrite(STDERR, (string) $e); | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
| @ -1,8 +0,0 @@ | ||||
| #!/usr/bin/env php | ||||
| <?php | ||||
| use PhpOffice\PhpSpreadsheet\Helper\Migrator; | ||||
| 
 | ||||
| require_once __DIR__ . '/../src/Bootstrap.php'; | ||||
| 
 | ||||
| $migrator = new Migrator(); | ||||
| $migrator->migrate(); | ||||
| @ -55,7 +55,8 @@ | ||||
|         "ext-zlib": "*", | ||||
|         "markbaker/complex": "^1.4", | ||||
|         "markbaker/matrix": "^1.2", | ||||
|         "psr/simple-cache": "^1.0" | ||||
|         "psr/simple-cache": "^1.0", | ||||
|         "maennchen/zipstream-php": "^2.0" | ||||
|     }, | ||||
|     "require-dev": { | ||||
|         "dompdf/dompdf": "^0.8.5", | ||||
|  | ||||
							
								
								
									
										344
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										344
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							| @ -4,8 +4,69 @@ | ||||
|         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||
|         "This file is @generated automatically" | ||||
|     ], | ||||
|     "content-hash": "9c60146d8c78c13d2610a2cec23339a2", | ||||
|     "content-hash": "ab06908c3ff8187971def16c578f1ced", | ||||
|     "packages": [ | ||||
|         { | ||||
|             "name": "maennchen/zipstream-php", | ||||
|             "version": "2.0.0", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/maennchen/ZipStream-PHP.git", | ||||
|                 "reference": "9ceee828f9620b2e5c075e551ec7ed8a7035ac95" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9ceee828f9620b2e5c075e551ec7ed8a7035ac95", | ||||
|                 "reference": "9ceee828f9620b2e5c075e551ec7ed8a7035ac95", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
|                 "ext-mbstring": "*", | ||||
|                 "myclabs/php-enum": "^1.5", | ||||
|                 "php": ">= 7.1", | ||||
|                 "psr/http-message": "^1.0" | ||||
|             }, | ||||
|             "require-dev": { | ||||
|                 "ext-zip": "*", | ||||
|                 "guzzlehttp/guzzle": ">= 6.3", | ||||
|                 "mikey179/vfsstream": "^1.6", | ||||
|                 "phpunit/phpunit": ">= 7.5" | ||||
|             }, | ||||
|             "type": "library", | ||||
|             "autoload": { | ||||
|                 "psr-4": { | ||||
|                     "ZipStream\\": "src/" | ||||
|                 } | ||||
|             }, | ||||
|             "notification-url": "https://packagist.org/downloads/", | ||||
|             "license": [ | ||||
|                 "MIT" | ||||
|             ], | ||||
|             "authors": [ | ||||
|                 { | ||||
|                     "name": "Paul Duncan", | ||||
|                     "email": "pabs@pablotron.org" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Jonatan Männchen", | ||||
|                     "email": "jonatan@maennchen.ch" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "Jesse Donat", | ||||
|                     "email": "donatj@gmail.com" | ||||
|                 }, | ||||
|                 { | ||||
|                     "name": "András Kolesár", | ||||
|                     "email": "kolesar@kolesar.hu" | ||||
|                 } | ||||
|             ], | ||||
|             "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", | ||||
|             "keywords": [ | ||||
|                 "stream", | ||||
|                 "zip" | ||||
|             ], | ||||
|             "time": "2020-02-23T01:48:39+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "markbaker/complex", | ||||
|             "version": "1.4.8", | ||||
| @ -170,6 +231,102 @@ | ||||
|             ], | ||||
|             "time": "2019-10-06T11:29:25+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "myclabs/php-enum", | ||||
|             "version": "1.7.6", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/myclabs/php-enum.git", | ||||
|                 "reference": "5f36467c7a87e20fbdc51e524fd8f9d1de80187c" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/myclabs/php-enum/zipball/5f36467c7a87e20fbdc51e524fd8f9d1de80187c", | ||||
|                 "reference": "5f36467c7a87e20fbdc51e524fd8f9d1de80187c", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
|                 "ext-json": "*", | ||||
|                 "php": ">=7.1" | ||||
|             }, | ||||
|             "require-dev": { | ||||
|                 "phpunit/phpunit": "^7", | ||||
|                 "squizlabs/php_codesniffer": "1.*", | ||||
|                 "vimeo/psalm": "^3.8" | ||||
|             }, | ||||
|             "type": "library", | ||||
|             "autoload": { | ||||
|                 "psr-4": { | ||||
|                     "MyCLabs\\Enum\\": "src/" | ||||
|                 } | ||||
|             }, | ||||
|             "notification-url": "https://packagist.org/downloads/", | ||||
|             "license": [ | ||||
|                 "MIT" | ||||
|             ], | ||||
|             "authors": [ | ||||
|                 { | ||||
|                     "name": "PHP Enum contributors", | ||||
|                     "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" | ||||
|                 } | ||||
|             ], | ||||
|             "description": "PHP Enum implementation", | ||||
|             "homepage": "http://github.com/myclabs/php-enum", | ||||
|             "keywords": [ | ||||
|                 "enum" | ||||
|             ], | ||||
|             "time": "2020-02-14T08:15:52+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "psr/http-message", | ||||
|             "version": "1.0.1", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/php-fig/http-message.git", | ||||
|                 "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", | ||||
|                 "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
|                 "php": ">=5.3.0" | ||||
|             }, | ||||
|             "type": "library", | ||||
|             "extra": { | ||||
|                 "branch-alias": { | ||||
|                     "dev-master": "1.0.x-dev" | ||||
|                 } | ||||
|             }, | ||||
|             "autoload": { | ||||
|                 "psr-4": { | ||||
|                     "Psr\\Http\\Message\\": "src/" | ||||
|                 } | ||||
|             }, | ||||
|             "notification-url": "https://packagist.org/downloads/", | ||||
|             "license": [ | ||||
|                 "MIT" | ||||
|             ], | ||||
|             "authors": [ | ||||
|                 { | ||||
|                     "name": "PHP-FIG", | ||||
|                     "homepage": "http://www.php-fig.org/" | ||||
|                 } | ||||
|             ], | ||||
|             "description": "Common interface for HTTP messages", | ||||
|             "homepage": "https://github.com/php-fig/http-message", | ||||
|             "keywords": [ | ||||
|                 "http", | ||||
|                 "http-message", | ||||
|                 "psr", | ||||
|                 "psr-7", | ||||
|                 "request", | ||||
|                 "response" | ||||
|             ], | ||||
|             "time": "2016-08-06T14:39:51+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "psr/simple-cache", | ||||
|             "version": "1.0.1", | ||||
| @ -323,6 +480,12 @@ | ||||
|                 "Xdebug", | ||||
|                 "performance" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://packagist.com", | ||||
|                     "type": "custom" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-01T12:26:26+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -667,6 +830,12 @@ | ||||
|                 } | ||||
|             ], | ||||
|             "description": "A tool to automatically fix PHP code style", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://github.com/keradus", | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-04-15T18:51:10+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -1703,6 +1872,16 @@ | ||||
|                 "testing", | ||||
|                 "xunit" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://phpunit.de/donate.html", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/sebastianbergmann", | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-04-23T04:39:42+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2566,6 +2745,12 @@ | ||||
|                 "fpdi", | ||||
|                 "pdf" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-23T15:53:59+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2693,6 +2878,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony Console Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-30T11:42:42+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2763,6 +2962,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony EventDispatcher Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2871,6 +3084,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony Filesystem Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2920,6 +3147,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony Finder Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -2974,6 +3215,20 @@ | ||||
|                 "configuration", | ||||
|                 "options" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3032,6 +3287,20 @@ | ||||
|                 "polyfill", | ||||
|                 "portable" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-02-27T09:26:54+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3091,6 +3360,20 @@ | ||||
|                 "portable", | ||||
|                 "shim" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-09T19:04:49+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3205,6 +3488,20 @@ | ||||
|                 "portable", | ||||
|                 "shim" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-02-27T09:26:54+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3263,6 +3560,20 @@ | ||||
|                 "portable", | ||||
|                 "shim" | ||||
|             ], | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-02-27T09:26:54+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3312,6 +3623,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony Process Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3420,6 +3745,20 @@ | ||||
|             ], | ||||
|             "description": "Symfony Stopwatch Component", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "funding": [ | ||||
|                 { | ||||
|                     "url": "https://symfony.com/sponsor", | ||||
|                     "type": "custom" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://github.com/fabpot", | ||||
|                     "type": "github" | ||||
|                 }, | ||||
|                 { | ||||
|                     "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2020-03-27T16:56:45+00:00" | ||||
|         }, | ||||
|         { | ||||
| @ -3594,5 +3933,6 @@ | ||||
|         "ext-zip": "*", | ||||
|         "ext-zlib": "*" | ||||
|     }, | ||||
|     "platform-dev": [] | ||||
|     "platform-dev": [], | ||||
|     "plugin-api-version": "1.1.0" | ||||
| } | ||||
|  | ||||
| @ -42,6 +42,13 @@ Use [composer](https://getcomposer.org) to install PhpSpreadsheet into your proj | ||||
| composer require phpoffice/phpspreadsheet | ||||
| ``` | ||||
| 
 | ||||
| Or also download the documentation and samples if you plan to use them: | ||||
| 
 | ||||
| ```sh | ||||
| composer require phpoffice/phpspreadsheet --prefer-source | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| ## Hello World | ||||
| 
 | ||||
| This would be the simplest way to write a spreadsheet: | ||||
| @ -64,8 +71,8 @@ $writer->save('hello world.xlsx'); | ||||
| 
 | ||||
| ## Learn by example | ||||
| 
 | ||||
| A good way to get started is to run some of the samples. Serve the samples via | ||||
| PHP built-in webserver: | ||||
| A good way to get started is to run some of the samples. Don't forget to download them via `--prefer-source` composer | ||||
| flag. And then serve them via PHP built-in webserver: | ||||
| 
 | ||||
| ```sh | ||||
| php -S localhost:8000 -t vendor/phpoffice/phpspreadsheet/samples | ||||
|  | ||||
| @ -200,6 +200,8 @@ ISREF               | **Not yet Implemented** | ||||
| ISTEXT              | \PhpOffice\PhpSpreadsheet\Calculation\Functions::isText | ||||
| N                   | \PhpOffice\PhpSpreadsheet\Calculation\Functions::n | ||||
| NA                  | \PhpOffice\PhpSpreadsheet\Calculation\Functions::NA | ||||
| SHEET               | **Not yet Implemented** | ||||
| SHEETS              | **Not yet Implemented** | ||||
| TYPE                | \PhpOffice\PhpSpreadsheet\Calculation\Functions::TYPE | ||||
| 
 | ||||
| ## CATEGORY_LOGICAL | ||||
| @ -272,6 +274,8 @@ EXP                 | exp | ||||
| FACT                | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACT | ||||
| FACTDOUBLE          | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACTDOUBLE | ||||
| FLOOR               | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOOR | ||||
| FLOOR.MATH          | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORMATH | ||||
| FLOOR.PRECISE       | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE | ||||
| GCD                 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD | ||||
| INT                 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::INT | ||||
| LCM                 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM | ||||
|  | ||||
| @ -170,6 +170,8 @@ FISHER              | CATEGORY_STATISTICAL           | \PhpOffice\PhpSpreadsheet | ||||
| FISHERINV           | CATEGORY_STATISTICAL           | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV | ||||
| FIXED               | CATEGORY_TEXT_AND_DATA         | \PhpOffice\PhpSpreadsheet\Calculation\TextData::FIXEDFORMAT | ||||
| FLOOR               | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOOR | ||||
| FLOOR.MATH          | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORMATH | ||||
| FLOOR.PRECISE       | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOORPRECISE | ||||
| FORECAST            | CATEGORY_STATISTICAL           | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FORECAST | ||||
| FORMULATEXT         | CATEGORY_LOOKUP_AND_REFERENCE  | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT | ||||
| FREQUENCY           | CATEGORY_STATISTICAL           | **Not yet Implemented** | ||||
| @ -419,6 +421,8 @@ SEC                 | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet | ||||
| SECH                | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH | ||||
| SECOND              | CATEGORY_DATE_AND_TIME         | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::SECOND | ||||
| SERIESSUM           | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM | ||||
| SHEET               | CATEGORY_INFORMATION           | **Not yet Implemented** | ||||
| SHEETS              | CATEGORY_INFORMATION           | **Not yet Implemented** | ||||
| SIGN                | CATEGORY_MATH_AND_TRIG         | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SIGN | ||||
| SIN                 | CATEGORY_MATH_AND_TRIG         | sin | ||||
| SINH                | CATEGORY_MATH_AND_TRIG         | sinh | ||||
|  | ||||
| @ -8,426 +8,15 @@ need to be done. | ||||
| 
 | ||||
| ## Automated tool | ||||
| 
 | ||||
| The tool is included in PhpSpreadsheet. It scans recursively all files | ||||
| and directories, starting from the current directory. Assuming it was | ||||
| installed with composer, it can be run like so: | ||||
| [RectorPHP](https://github.com/rectorphp/rector) can be used to migrate | ||||
| automatically your codebase. Assuming your files to be migrated lives | ||||
| in `src/`, you can run the migration like so: | ||||
| 
 | ||||
| ``` sh | ||||
| cd /project/to/migrate/src | ||||
| php /project/to/migrate/vendor/phpoffice/phpspreadsheet/bin/migrate-from-phpexcel | ||||
| composer require rector/rector --dev | ||||
| vendor/bin/rector process src --set phpexcel-to-phpspreadsheet | ||||
| composer remove rector/rector | ||||
| ``` | ||||
| 
 | ||||
| **Important** The tool will irreversibly modify your sources, be sure to | ||||
| backup everything, and double check the result before committing. | ||||
| 
 | ||||
| ## Manual changes | ||||
| 
 | ||||
| In addition to automated changes, a few things need to be migrated manually. | ||||
| 
 | ||||
| ### Renamed readers and writers | ||||
| 
 | ||||
| When using `IOFactory::createReader()`, `IOFactory::createWriter()` and | ||||
| `IOFactory::identify()`, the reader/writer short names are used. Those were | ||||
| changed, along as their corresponding class, to remove ambiguity: | ||||
| 
 | ||||
| Before           | After | ||||
| -----------------|--------- | ||||
| `'CSV'`          | `'Csv'` | ||||
| `'Excel2003XML'` | `'Xml'` | ||||
| `'Excel2007'`    | `'Xlsx'` | ||||
| `'Excel5'`       | `'Xls'` | ||||
| `'Gnumeric'`     | `'Gnumeric'` | ||||
| `'HTML'`         | `'Html'` | ||||
| `'OOCalc'`       | `'Ods'` | ||||
| `'OpenDocument'` | `'Ods'` | ||||
| `'PDF'`          | `'Pdf'` | ||||
| `'SYLK'`         | `'Slk'` | ||||
| 
 | ||||
| ### Simplified IOFactory | ||||
| 
 | ||||
| The following methods : | ||||
| 
 | ||||
| - `PHPExcel_IOFactory::getSearchLocations()` | ||||
| - `PHPExcel_IOFactory::setSearchLocations()` | ||||
| - `PHPExcel_IOFactory::addSearchLocation()` | ||||
| 
 | ||||
| were replaced by `IOFactory::registerReader()` and `IOFactory::registerWriter()`. That means | ||||
| IOFactory now relies on classes autoloading. | ||||
| 
 | ||||
| Before: | ||||
| 
 | ||||
| ```php | ||||
| \PHPExcel_IOFactory::addSearchLocation($type, $location, $classname); | ||||
| ``` | ||||
| 
 | ||||
| After: | ||||
| 
 | ||||
| ```php | ||||
| \PhpOffice\PhpSpreadsheet\IOFactory::registerReader($type, $classname); | ||||
| ``` | ||||
| 
 | ||||
| ### Removed deprecated things | ||||
| 
 | ||||
| #### Worksheet::duplicateStyleArray() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $worksheet->duplicateStyleArray($styles, $range, $advanced); | ||||
| 
 | ||||
| // After | ||||
| $worksheet->getStyle($range)->applyFromArray($styles, $advanced); | ||||
| ``` | ||||
| 
 | ||||
| #### DataType::dataTypeForValue() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| DataType::dataTypeForValue($value); | ||||
| 
 | ||||
| // After | ||||
| DefaultValueBinder::dataTypeForValue($value); | ||||
| ``` | ||||
| 
 | ||||
| #### Conditional::getCondition() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $conditional->getCondition(); | ||||
| 
 | ||||
| // After | ||||
| $conditional->getConditions()[0]; | ||||
| ``` | ||||
| 
 | ||||
| #### Conditional::setCondition() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $conditional->setCondition($value); | ||||
| 
 | ||||
| // After | ||||
| $conditional->setConditions($value); | ||||
| ``` | ||||
| 
 | ||||
| #### Worksheet::getDefaultStyle() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $worksheet->getDefaultStyle(); | ||||
| 
 | ||||
| // After | ||||
| $worksheet->getParent()->getDefaultStyle(); | ||||
| ``` | ||||
| 
 | ||||
| #### Worksheet::setDefaultStyle() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $worksheet->setDefaultStyle($value); | ||||
| 
 | ||||
| // After | ||||
| $worksheet->getParent()->getDefaultStyle()->applyFromArray([ | ||||
|     'font' => [ | ||||
|         'name' => $pValue->getFont()->getName(), | ||||
|         'size' => $pValue->getFont()->getSize(), | ||||
|     ], | ||||
| ]); | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| #### Worksheet::setSharedStyle() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $worksheet->setSharedStyle($sharedStyle, $range); | ||||
| 
 | ||||
| // After | ||||
| $worksheet->duplicateStyle($sharedStyle, $range); | ||||
| ``` | ||||
| 
 | ||||
| #### Worksheet::getSelectedCell() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $worksheet->getSelectedCell(); | ||||
| 
 | ||||
| // After | ||||
| $worksheet->getSelectedCells(); | ||||
| ``` | ||||
| 
 | ||||
| #### Writer\Xls::setTempDir() | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $writer->setTempDir(); | ||||
| 
 | ||||
| // After, there is no way to set temporary storage directory anymore | ||||
| ``` | ||||
| 
 | ||||
| ### Autoloader | ||||
| 
 | ||||
| The class `PHPExcel_Autoloader` was removed entirely and is replaced by composer | ||||
| autoloading mechanism. | ||||
| 
 | ||||
| ### Writing PDF | ||||
| 
 | ||||
| PDF libraries must be installed via composer. And the following methods were removed | ||||
| and are replaced by `IOFactory::registerWriter()` instead: | ||||
| 
 | ||||
| - `PHPExcel_Settings::getPdfRenderer()` | ||||
| - `PHPExcel_Settings::setPdfRenderer()` | ||||
| - `PHPExcel_Settings::getPdfRendererName()` | ||||
| - `PHPExcel_Settings::setPdfRendererName()` | ||||
| 
 | ||||
| Before: | ||||
| 
 | ||||
| ```php | ||||
| \PHPExcel_Settings::setPdfRendererName(PHPExcel_Settings::PDF_RENDERER_MPDF); | ||||
| \PHPExcel_Settings::setPdfRenderer($somePath); | ||||
| $writer = \PHPExcel_IOFactory::createWriter($spreadsheet, 'PDF'); | ||||
| ``` | ||||
| 
 | ||||
| After: | ||||
| 
 | ||||
| ```php | ||||
| $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Mpdf'); | ||||
| 
 | ||||
| // Or alternatively | ||||
| \PhpOffice\PhpSpreadsheet\IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); | ||||
| $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf'); | ||||
| 
 | ||||
| // Or alternatively | ||||
| $writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); | ||||
| ``` | ||||
| 
 | ||||
| ### Rendering charts | ||||
| 
 | ||||
| When rendering charts for HTML or PDF outputs, the process was also simplified. And while | ||||
| JpGraph support is still available, it is unfortunately not up to date for latest PHP versions | ||||
| and it will generate various warnings. | ||||
| 
 | ||||
| If you rely on this feature, please consider | ||||
| contributing either patches to JpGraph or another `IRenderer` implementation (a good | ||||
| candidate might be [CpChart](https://github.com/szymach/c-pchart)). | ||||
| 
 | ||||
| Before: | ||||
| 
 | ||||
| ```php | ||||
| $rendererName = \PHPExcel_Settings::CHART_RENDERER_JPGRAPH; | ||||
| $rendererLibrary = 'jpgraph3.5.0b1/src/'; | ||||
| $rendererLibraryPath = '/php/libraries/Charts/' . $rendererLibrary; | ||||
| 
 | ||||
| \PHPExcel_Settings::setChartRenderer($rendererName, $rendererLibraryPath); | ||||
| ``` | ||||
| 
 | ||||
| After: | ||||
| 
 | ||||
| Require the dependency via composer: | ||||
| 
 | ||||
| ```sh | ||||
| composer require jpgraph/jpgraph | ||||
| ``` | ||||
| 
 | ||||
| And then: | ||||
| 
 | ||||
| ```php | ||||
| Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); | ||||
| ``` | ||||
| 
 | ||||
| ### PclZip and ZipArchive | ||||
| 
 | ||||
| Support for PclZip were dropped in favor of the more complete and modern | ||||
| [PHP extension ZipArchive](https://php.net/manual/en/book.zip.php). | ||||
| So the following were removed: | ||||
| 
 | ||||
| - `PclZip` | ||||
| - `PHPExcel_Settings::setZipClass()` | ||||
| - `PHPExcel_Settings::getZipClass()` | ||||
| - `PHPExcel_Shared_ZipArchive` | ||||
| - `PHPExcel_Shared_ZipStreamWrapper` | ||||
| 
 | ||||
| ### Cell caching | ||||
| 
 | ||||
| Cell caching was heavily refactored to leverage | ||||
| [PSR-16](https://www.php-fig.org/psr/psr-16/). That means most classes | ||||
| related to that feature were removed: | ||||
| 
 | ||||
| - `PHPExcel_CachedObjectStorage_APC` | ||||
| - `PHPExcel_CachedObjectStorage_DiscISAM` | ||||
| - `PHPExcel_CachedObjectStorage_ICache` | ||||
| - `PHPExcel_CachedObjectStorage_Igbinary` | ||||
| - `PHPExcel_CachedObjectStorage_Memcache` | ||||
| - `PHPExcel_CachedObjectStorage_Memory` | ||||
| - `PHPExcel_CachedObjectStorage_MemoryGZip` | ||||
| - `PHPExcel_CachedObjectStorage_MemorySerialized` | ||||
| - `PHPExcel_CachedObjectStorage_PHPTemp` | ||||
| - `PHPExcel_CachedObjectStorage_SQLite` | ||||
| - `PHPExcel_CachedObjectStorage_SQLite3` | ||||
| - `PHPExcel_CachedObjectStorage_Wincache` | ||||
| 
 | ||||
| In addition to that, `\PhpOffice\PhpSpreadsheet::getCellCollection()` was renamed | ||||
| to `\PhpOffice\PhpSpreadsheet::getCoordinates()` and | ||||
| `\PhpOffice\PhpSpreadsheet::getCellCacheController()` to | ||||
| `\PhpOffice\PhpSpreadsheet::getCellCollection()` for clarity. | ||||
| 
 | ||||
| Refer to [the new documentation](./memory_saving.md) to see how to migrate. | ||||
| 
 | ||||
| ### Dropped conditionally returned cell | ||||
| 
 | ||||
| For all the following methods, it is no more possible to change the type of | ||||
| returned value. It always return the Worksheet and never the Cell or Rule: | ||||
| 
 | ||||
| - Worksheet::setCellValue() | ||||
| - Worksheet::setCellValueByColumnAndRow() | ||||
| - Worksheet::setCellValueExplicit() | ||||
| - Worksheet::setCellValueExplicitByColumnAndRow() | ||||
| - Worksheet::addRule() | ||||
| 
 | ||||
| Migration would be similar to: | ||||
| 
 | ||||
| ``` php | ||||
| // Before | ||||
| $cell = $worksheet->setCellValue('A1', 'value', true); | ||||
| 
 | ||||
| // After | ||||
| $cell = $worksheet->getCell('A1')->setValue('value'); | ||||
| ``` | ||||
| 
 | ||||
| ### Standardized keys for styling | ||||
| 
 | ||||
| Array keys used for styling have been standardized for a more coherent experience. | ||||
| It now uses the same wording and casing as the getter and setter: | ||||
| 
 | ||||
| ```php | ||||
| // Before | ||||
| $style = [ | ||||
|     'numberformat' => [ | ||||
|         'code' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE, | ||||
|     ], | ||||
|     'font' => [ | ||||
|         'strike' => true, | ||||
|         'superScript' => true, | ||||
|         'subScript' => true, | ||||
|     ], | ||||
|     'alignment' => [ | ||||
|         'rotation' => 90, | ||||
|         'readorder' => Alignment::READORDER_RTL, | ||||
|         'wrap' => true, | ||||
|     ], | ||||
|     'borders' => [ | ||||
|         'diagonaldirection' => Borders::DIAGONAL_BOTH, | ||||
|         'allborders' => [ | ||||
|             'style' => Border::BORDER_THIN, | ||||
|         ], | ||||
|     ], | ||||
|     'fill' => [ | ||||
|         'type' => Fill::FILL_GRADIENT_LINEAR, | ||||
|         'startcolor' => [ | ||||
|             'argb' => 'FFA0A0A0', | ||||
|         ], | ||||
|         'endcolor' => [ | ||||
|             'argb' => 'FFFFFFFF', | ||||
|         ], | ||||
|     ], | ||||
| ]; | ||||
| 
 | ||||
| // After | ||||
| $style = [ | ||||
|     'numberFormat' => [ | ||||
|         'formatCode' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE, | ||||
|     ], | ||||
|     'font' => [ | ||||
|         'strikethrough' => true, | ||||
|         'superscript' => true, | ||||
|         'subscript' => true, | ||||
|     ], | ||||
|     'alignment' => [ | ||||
|         'textRotation' => 90, | ||||
|         'readOrder' => Alignment::READORDER_RTL, | ||||
|         'wrapText' => true, | ||||
|     ], | ||||
|     'borders' => [ | ||||
|         'diagonalDirection' => Borders::DIAGONAL_BOTH, | ||||
|         'allBorders' => [ | ||||
|             'borderStyle' => Border::BORDER_THIN, | ||||
|         ], | ||||
|     ], | ||||
|     'fill' => [ | ||||
|         'fillType' => Fill::FILL_GRADIENT_LINEAR, | ||||
|         'startColor' => [ | ||||
|             'argb' => 'FFA0A0A0', | ||||
|         ], | ||||
|         'endColor' => [ | ||||
|             'argb' => 'FFFFFFFF', | ||||
|         ], | ||||
|     ], | ||||
| ]; | ||||
| ``` | ||||
| 
 | ||||
| ### Dedicated class to manipulate coordinates | ||||
| 
 | ||||
| Methods to manipulate coordinates that used to exists in `PHPExcel_Cell` were extracted | ||||
| to a dedicated new class `\PhpOffice\PhpSpreadsheet\Cell\Coordinate`. The methods are: | ||||
| 
 | ||||
| - `absoluteCoordinate()` | ||||
| - `absoluteReference()` | ||||
| - `buildRange()` | ||||
| - `columnIndexFromString()` | ||||
| - `coordinateFromString()` | ||||
| - `extractAllCellReferencesInRange()` | ||||
| - `getRangeBoundaries()` | ||||
| - `mergeRangesInCollection()` | ||||
| - `rangeBoundaries()` | ||||
| - `rangeDimension()` | ||||
| - `splitRange()` | ||||
| - `stringFromColumnIndex()` | ||||
| 
 | ||||
| ### Column index based on 1 | ||||
| 
 | ||||
| Column indexes are now based on 1. So column `A` is the index `1`. This is consistent | ||||
| with rows starting at 1 and Excel function `COLUMN()` that returns `1` for column `A`. | ||||
| So the code must be adapted with something like: | ||||
| 
 | ||||
| ```php | ||||
| // Before | ||||
| $cell = $worksheet->getCellByColumnAndRow($column, $row); | ||||
| 
 | ||||
| for ($column = 0; $column < $max; $column++) { | ||||
|     $worksheet->setCellValueByColumnAndRow($column, $row, 'value ' . $column); | ||||
| } | ||||
| 
 | ||||
| // After | ||||
| $cell = $worksheet->getCellByColumnAndRow($column + 1, $row); | ||||
| 
 | ||||
| for ($column = 1; $column <= $max; $column++) { | ||||
|     $worksheet->setCellValueByColumnAndRow($column, $row, 'value ' . $column); | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| All the following methods are affected: | ||||
| 
 | ||||
| - `PHPExcel_Worksheet::cellExistsByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::freezePaneByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::getCellByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::getColumnDimensionByColumn()` | ||||
| - `PHPExcel_Worksheet::getCommentByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::getStyleByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::insertNewColumnBeforeByIndex()` | ||||
| - `PHPExcel_Worksheet::mergeCellsByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::protectCellsByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::removeColumnByIndex()` | ||||
| - `PHPExcel_Worksheet::setAutoFilterByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::setBreakByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::setCellValueByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::setCellValueExplicitByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::setSelectedCellByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::stringFromColumnIndex()` | ||||
| - `PHPExcel_Worksheet::unmergeCellsByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet::unprotectCellsByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet_PageSetup::addPrintAreaByColumnAndRow()` | ||||
| - `PHPExcel_Worksheet_PageSetup::setPrintAreaByColumnAndRow()` | ||||
| 
 | ||||
| ### Removed default values | ||||
| 
 | ||||
| Default values for many methods were removed when it did not make sense. Typically, | ||||
| setter methods should not have default values. For a complete list of methods and | ||||
| their original default values, see [that commit](https://github.com/PHPOffice/PhpSpreadsheet/commit/033a4bdad56340795a5bf7ec3c8a2fde005cda24). | ||||
| For more details, see | ||||
| [RectorPHP blog post](https://getrector.org/blog/2020/04/16/how-to-migrate-from-phpexcel-to-phpspreadsheet-with-rector-in-30-minutes). | ||||
|  | ||||
| @ -535,8 +535,12 @@ $writer->save("05featuredemo.csv"); | ||||
| 
 | ||||
| #### Writing UTF-8 CSV files | ||||
| 
 | ||||
| A CSV file can be marked as UTF-8 by writing a BOM file header. This can | ||||
| be enabled by using the following code: | ||||
| CSV files are written in UTF-8. If they do not contain characters | ||||
| outside the ASCII range, nothing else need be done. | ||||
| However, if such characters are in the file, | ||||
| it should explicitly include a BOM file header; | ||||
| if it doesn't, Excel will not interpret those characters correctly. | ||||
| This can be enabled by using the following code: | ||||
| 
 | ||||
| ``` php | ||||
| $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); | ||||
| @ -677,35 +681,26 @@ Supported methods: | ||||
| -   `generateStyles()` | ||||
| -   `generateSheetData()` | ||||
| -   `generateHTMLFooter()` | ||||
| -   `generateHTMLAll()` | ||||
| 
 | ||||
| Here's an example which retrieves all parts independently and merges | ||||
| them into a resulting HTML page: | ||||
| 
 | ||||
| ``` php | ||||
| <?php | ||||
| $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); | ||||
| echo $writer->generateHTMLHeader(); | ||||
| ?> | ||||
| 
 | ||||
| <style> | ||||
| <!-- | ||||
| $hdr = $writer->generateHTMLHeader(); | ||||
| $sty = $writer->generateStyles(false); // do not write <style> and </style> | ||||
| $newstyle = <<<EOF | ||||
| <style type='text/css'> | ||||
| $sty | ||||
| html { | ||||
|     font-family: Times New Roman; | ||||
|     font-size: 9pt; | ||||
|     background-color: white; | ||||
|     background-color: yellow; | ||||
| } | ||||
| 
 | ||||
| <?php | ||||
| echo $writer->generateStyles(false); // do not write <style> and </style> | ||||
| ?> | ||||
| 
 | ||||
| --> | ||||
| </style> | ||||
| 
 | ||||
| <?php | ||||
| EOF; | ||||
| echo preg_replace('@</head>@', "$newstyle\n</head>", $hdr); | ||||
| echo $writer->generateSheetData(); | ||||
| echo $writer->generateHTMLFooter(); | ||||
| ?> | ||||
| ``` | ||||
| 
 | ||||
| #### Writing UTF-8 HTML files | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <phpunit | ||||
|         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd" | ||||
|         xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" | ||||
|         bootstrap="./tests/bootstrap.php" | ||||
|         backupGlobals="true" | ||||
|         colors="true" | ||||
| @ -11,7 +11,7 @@ | ||||
|         <ini name="memory_limit" value="2048M"/> | ||||
|     </php> | ||||
|     <testsuite name="PhpSpreadsheet Unit Test Suite"> | ||||
|         <directory suffix="Test.php">./tests/PhpSpreadsheetTests</directory> | ||||
|         <directory>./tests/PhpSpreadsheetTests</directory> | ||||
|     </testsuite> | ||||
|     <filter> | ||||
|         <whitelist> | ||||
|  | ||||
| @ -59,18 +59,18 @@ foreach ($years as $year) { | ||||
|                     $period, | ||||
|                     $i | ||||
|                 ); | ||||
|                 $value = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                 $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 $salesValue = $invoiceValue = null; | ||||
|                 $incomeOrExpenditure = rand(-1, 1); | ||||
|                 $incomeOrExpenditure = mt_rand(-1, 1); | ||||
|                 if ($incomeOrExpenditure == -1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = null; | ||||
|                 } elseif ($incomeOrExpenditure == 1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } else { | ||||
|                     $expenditure = null; | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } | ||||
|                 $dataArray = [$year, | ||||
|                     $period, | ||||
|  | ||||
| @ -59,18 +59,18 @@ foreach ($years as $year) { | ||||
|                     $period, | ||||
|                     $i | ||||
|                 ); | ||||
|                 $value = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                 $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 $salesValue = $invoiceValue = null; | ||||
|                 $incomeOrExpenditure = rand(-1, 1); | ||||
|                 $incomeOrExpenditure = mt_rand(-1, 1); | ||||
|                 if ($incomeOrExpenditure == -1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = null; | ||||
|                 } elseif ($incomeOrExpenditure == 1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } else { | ||||
|                     $expenditure = null; | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } | ||||
|                 $dataArray = [$year, | ||||
|                     $period, | ||||
|  | ||||
| @ -59,18 +59,18 @@ foreach ($years as $year) { | ||||
|                     $period, | ||||
|                     $i | ||||
|                 ); | ||||
|                 $value = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                 $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 $salesValue = $invoiceValue = null; | ||||
|                 $incomeOrExpenditure = rand(-1, 1); | ||||
|                 $incomeOrExpenditure = mt_rand(-1, 1); | ||||
|                 if ($incomeOrExpenditure == -1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = null; | ||||
|                 } elseif ($incomeOrExpenditure == 1) { | ||||
|                     $expenditure = rand(-500, -1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } else { | ||||
|                     $expenditure = null; | ||||
|                     $income = rand(500, 1000) * (1 + (rand(-1, 1) / 4)); | ||||
|                     $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); | ||||
|                 } | ||||
|                 $dataArray = [$year, | ||||
|                     $period, | ||||
|  | ||||
| @ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Helper\Sample; | ||||
| use PhpOffice\PhpSpreadsheet\IOFactory; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| 
 | ||||
| require_once __DIR__ . '/../../src/Bootstrap.php'; | ||||
| require_once __DIR__ . '/../Bootstrap.php'; | ||||
| 
 | ||||
| $helper = new Sample(); | ||||
| if ($helper->isCli()) { | ||||
|  | ||||
| @ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Helper\Sample; | ||||
| use PhpOffice\PhpSpreadsheet\IOFactory; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| 
 | ||||
| require_once __DIR__ . '/../../src/Bootstrap.php'; | ||||
| require_once __DIR__ . '/../Bootstrap.php'; | ||||
| 
 | ||||
| $helper = new Sample(); | ||||
| if ($helper->isCli()) { | ||||
|  | ||||
| @ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Helper\Sample; | ||||
| use PhpOffice\PhpSpreadsheet\IOFactory; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| 
 | ||||
| require_once __DIR__ . '/../../src/Bootstrap.php'; | ||||
| require_once __DIR__ . '/../Bootstrap.php'; | ||||
| 
 | ||||
| $helper = new Sample(); | ||||
| if ($helper->isCli()) { | ||||
|  | ||||
| @ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\Helper\Sample; | ||||
| use PhpOffice\PhpSpreadsheet\IOFactory; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| 
 | ||||
| require_once __DIR__ . '/../../src/Bootstrap.php'; | ||||
| require_once __DIR__ . '/../Bootstrap.php'; | ||||
| 
 | ||||
| $helper = new Sample(); | ||||
| if ($helper->isCli()) { | ||||
|  | ||||
| @ -16,7 +16,7 @@ $spreadsheet->getActiveSheet()->setCellValue('A1', '=B1') | ||||
|     ->setCellValue('B1', '=A1+1') | ||||
|     ->setCellValue('B2', '=A2'); | ||||
| 
 | ||||
| Calculation::getInstance($spreadsheet)->cyclicFormulaCount = 100; | ||||
| Calculation::getInstance($spreadsheet)->cyclicFormulaCount = 15; | ||||
| 
 | ||||
| // Calculated data
 | ||||
| $helper->log('Calculated data'); | ||||
|  | ||||
							
								
								
									
										14
									
								
								samples/Basic/17a_Html.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								samples/Basic/17a_Html.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| <?php | ||||
| 
 | ||||
| use PhpOffice\PhpSpreadsheet\Writer\Html; | ||||
| 
 | ||||
| require __DIR__ . '/../Header.php'; | ||||
| $spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; | ||||
| 
 | ||||
| $filename = $helper->getFilename(__FILE__, 'html'); | ||||
| $writer = new Html($spreadsheet); | ||||
| 
 | ||||
| $callStartTime = microtime(true); | ||||
| $writer->setEmbedImages(true); | ||||
| $writer->save($filename); | ||||
| $helper->logWrite($writer, $filename, $callStartTime); | ||||
| @ -26,22 +26,22 @@ $spreadsheet->setActiveSheetIndex(0); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->getStyle('A1:T100')->applyFromArray( | ||||
|     ['fill' => [ | ||||
|                 'fillType' => Fill::FILL_SOLID, | ||||
|                 'color' => ['argb' => 'FFCCFFCC'], | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|                 'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|             ], | ||||
|         ] | ||||
|         'fillType' => Fill::FILL_SOLID, | ||||
|         'color' => ['argb' => 'FFCCFFCC'], | ||||
|     ], | ||||
|         'borders' => [ | ||||
|             'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|             'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->getStyle('C5:R95')->applyFromArray( | ||||
|     ['fill' => [ | ||||
|                 'fillType' => Fill::FILL_SOLID, | ||||
|                 'color' => ['argb' => 'FFFFFF00'], | ||||
|             ], | ||||
|         ] | ||||
|         'fillType' => Fill::FILL_SOLID, | ||||
|         'color' => ['argb' => 'FFFFFF00'], | ||||
|     ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Save
 | ||||
|  | ||||
| @ -30,26 +30,26 @@ $sharedStyle2 = new Style(); | ||||
| 
 | ||||
| $sharedStyle1->applyFromArray( | ||||
|     ['fill' => [ | ||||
|                 'fillType' => Fill::FILL_SOLID, | ||||
|                 'color' => ['argb' => 'FFCCFFCC'], | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|                 'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|             ], | ||||
|         ] | ||||
|         'fillType' => Fill::FILL_SOLID, | ||||
|         'color' => ['argb' => 'FFCCFFCC'], | ||||
|     ], | ||||
|         'borders' => [ | ||||
|             'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|             'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $sharedStyle2->applyFromArray( | ||||
|     ['fill' => [ | ||||
|                 'fillType' => Fill::FILL_SOLID, | ||||
|                 'color' => ['argb' => 'FFFFFF00'], | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|                 'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|             ], | ||||
|         ] | ||||
|         'fillType' => Fill::FILL_SOLID, | ||||
|         'color' => ['argb' => 'FFFFFF00'], | ||||
|     ], | ||||
|         'borders' => [ | ||||
|             'bottom' => ['borderStyle' => Border::BORDER_THIN], | ||||
|             'right' => ['borderStyle' => Border::BORDER_MEDIUM], | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->duplicateStyle($sharedStyle1, 'A1:T100'); | ||||
|  | ||||
| @ -21,7 +21,11 @@ $spreadsheet->getProperties()->setCreator('Maarten Balliauw') | ||||
| 
 | ||||
| // Generate an image
 | ||||
| $helper->log('Generate an image'); | ||||
| $gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream'); | ||||
| $gdImage = @imagecreatetruecolor(120, 20); | ||||
| if (!$gdImage) { | ||||
|     die('Cannot Initialize new GD image stream'); | ||||
| } | ||||
| 
 | ||||
| $textColor = imagecolorallocate($gdImage, 255, 255, 255); | ||||
| imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor); | ||||
| 
 | ||||
| @ -35,6 +39,7 @@ $drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); | ||||
| $drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); | ||||
| $drawing->setHeight(36); | ||||
| $drawing->setWorksheet($spreadsheet->getActiveSheet()); | ||||
| $drawing->setCoordinates('C5'); | ||||
| 
 | ||||
| // Save
 | ||||
| $helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html']); | ||||
|  | ||||
| @ -11,9 +11,9 @@ $spreadsheet = $reader->load(__DIR__ . '/../templates/30template.xls'); | ||||
| 
 | ||||
| $helper->log('Add new data to the template'); | ||||
| $data = [['title' => 'Excel for dummies', | ||||
|         'price' => 17.99, | ||||
|         'quantity' => 2, | ||||
|     ], | ||||
|     'price' => 17.99, | ||||
|     'quantity' => 2, | ||||
| ], | ||||
|     ['title' => 'PHP for dummies', | ||||
|         'price' => 15.99, | ||||
|         'quantity' => 1, | ||||
|  | ||||
| @ -15,12 +15,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -83,7 +83,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -15,12 +15,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -86,7 +86,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -15,12 +15,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -86,7 +86,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -15,20 +15,20 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', '', 'Budget', 'Forecast', 'Actual'], | ||||
|             ['2010', 'Q1', 47, 44, 43], | ||||
|             ['', 'Q2', 56, 53, 50], | ||||
|             ['', 'Q3', 52, 46, 45], | ||||
|             ['', 'Q4', 45, 40, 40], | ||||
|             ['2011', 'Q1', 51, 42, 46], | ||||
|             ['', 'Q2', 53, 58, 56], | ||||
|             ['', 'Q3', 64, 66, 69], | ||||
|             ['', 'Q4', 54, 55, 56], | ||||
|             ['2012', 'Q1', 49, 52, 58], | ||||
|             ['', 'Q2', 68, 73, 86], | ||||
|             ['', 'Q3', 72, 78, 0], | ||||
|             ['', 'Q4', 50, 60, 0], | ||||
|         ] | ||||
|         ['', '', 'Budget', 'Forecast', 'Actual'], | ||||
|         ['2010', 'Q1', 47, 44, 43], | ||||
|         ['', 'Q2', 56, 53, 50], | ||||
|         ['', 'Q3', 52, 46, 45], | ||||
|         ['', 'Q4', 45, 40, 40], | ||||
|         ['2011', 'Q1', 51, 42, 46], | ||||
|         ['', 'Q2', 53, 58, 56], | ||||
|         ['', 'Q3', 64, 66, 69], | ||||
|         ['', 'Q4', 54, 55, 56], | ||||
|         ['2012', 'Q1', 49, 52, 58], | ||||
|         ['', 'Q2', 68, 73, 86], | ||||
|         ['', 'Q3', 72, 78, 0], | ||||
|         ['', 'Q4', 50, 60, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -95,7 +95,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     $xAxisLabel, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -15,20 +15,20 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 'Rainfall (mm)', 'Temperature (°F)', 'Humidity (%)'], | ||||
|             ['Jan', 78, 52, 61], | ||||
|             ['Feb', 64, 54, 62], | ||||
|             ['Mar', 62, 57, 63], | ||||
|             ['Apr', 21, 62, 59], | ||||
|             ['May', 11, 75, 60], | ||||
|             ['Jun', 1, 75, 57], | ||||
|             ['Jul', 1, 79, 56], | ||||
|             ['Aug', 1, 79, 59], | ||||
|             ['Sep', 10, 75, 60], | ||||
|             ['Oct', 40, 68, 63], | ||||
|             ['Nov', 69, 62, 64], | ||||
|             ['Dec', 89, 57, 66], | ||||
|         ] | ||||
|         ['', 'Rainfall (mm)', 'Temperature (°F)', 'Humidity (%)'], | ||||
|         ['Jan', 78, 52, 61], | ||||
|         ['Feb', 64, 54, 62], | ||||
|         ['Mar', 62, 57, 63], | ||||
|         ['Apr', 21, 62, 59], | ||||
|         ['May', 11, 75, 60], | ||||
|         ['Jun', 1, 75, 57], | ||||
|         ['Jul', 1, 79, 56], | ||||
|         ['Aug', 1, 79, 59], | ||||
|         ['Sep', 10, 75, 60], | ||||
|         ['Oct', 40, 68, 63], | ||||
|         ['Nov', 69, 62, 64], | ||||
|         ['Dec', 89, 57, 66], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -139,7 +139,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -84,7 +84,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -15,12 +15,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -83,7 +83,7 @@ $chart1 = new Chart( | ||||
|     $legend1, // legend
 | ||||
|     $plotArea1, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel1 // yAxisLabel
 | ||||
| ); | ||||
| @ -158,7 +158,7 @@ $chart2 = new Chart( | ||||
|     $legend2, // legend
 | ||||
|     $plotArea2, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel2 // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -16,12 +16,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -84,7 +84,7 @@ $chart1 = new Chart( | ||||
|     $legend1, // legend
 | ||||
|     $plotArea1, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel - Pie charts don't have a Y-Axis
 | ||||
| ); | ||||
| @ -154,7 +154,7 @@ $chart2 = new Chart( | ||||
|     null, // legend
 | ||||
|     $plotArea2, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis
 | ||||
| ); | ||||
|  | ||||
| @ -16,12 +16,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Custom colors for dataSeries (gray, blue, red, orange)
 | ||||
| @ -90,7 +90,7 @@ $chart1 = new Chart( | ||||
|     $legend1, // legend
 | ||||
|     $plotArea1, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel - Pie charts don't have a Y-Axis
 | ||||
| ); | ||||
| @ -162,7 +162,7 @@ $chart2 = new Chart( | ||||
|     null, // legend
 | ||||
|     $plotArea2, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis
 | ||||
| ); | ||||
|  | ||||
| @ -16,20 +16,20 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Jan', 47, 45, 71], | ||||
|             ['Feb', 56, 73, 86], | ||||
|             ['Mar', 52, 61, 69], | ||||
|             ['Apr', 40, 52, 60], | ||||
|             ['May', 42, 55, 71], | ||||
|             ['Jun', 58, 63, 76], | ||||
|             ['Jul', 53, 61, 89], | ||||
|             ['Aug', 46, 69, 85], | ||||
|             ['Sep', 62, 75, 81], | ||||
|             ['Oct', 51, 70, 96], | ||||
|             ['Nov', 55, 66, 89], | ||||
|             ['Dec', 68, 62, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Jan', 47, 45, 71], | ||||
|         ['Feb', 56, 73, 86], | ||||
|         ['Mar', 52, 61, 69], | ||||
|         ['Apr', 40, 52, 60], | ||||
|         ['May', 42, 55, 71], | ||||
|         ['Jun', 58, 63, 76], | ||||
|         ['Jul', 53, 61, 89], | ||||
|         ['Aug', 46, 69, 85], | ||||
|         ['Sep', 62, 75, 81], | ||||
|         ['Oct', 51, 70, 96], | ||||
|         ['Nov', 55, 66, 89], | ||||
|         ['Dec', 68, 62, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -96,7 +96,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     null   // yAxisLabel - Radar charts don't have a Y-Axis
 | ||||
| ); | ||||
|  | ||||
| @ -15,12 +15,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -80,7 +80,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -16,13 +16,13 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|     ['Counts', 'Max', 'Min', 'Min Threshold', 'Max Threshold'], | ||||
|     [10, 10, 5, 0, 50], | ||||
|     [30, 20, 10, 0, 50], | ||||
|     [20, 30, 15, 0, 50], | ||||
|     [40, 10, 0, 0, 50], | ||||
|     [100, 40, 5, 0, 50], | ||||
|         ], | ||||
|         ['Counts', 'Max', 'Min', 'Min Threshold', 'Max Threshold'], | ||||
|         [10, 10, 5, 0, 50], | ||||
|         [30, 20, 10, 0, 50], | ||||
|         [20, 30, 15, 0, 50], | ||||
|         [40, 10, 0, 0, 50], | ||||
|         [100, 40, 5, 0, 50], | ||||
|     ], | ||||
|     null, | ||||
|     'A1', | ||||
|     true | ||||
| @ -92,7 +92,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     $xAxisLabel, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -20,11 +20,11 @@ $helper->log('Update cell data values that are displayed in the chart'); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|     [50 - 12, 50 - 15, 50 - 21], | ||||
|     [50 - 56, 50 - 73, 50 - 86], | ||||
|     [50 - 52, 50 - 61, 50 - 69], | ||||
|     [50 - 30, 50 - 32, 50], | ||||
|         ], | ||||
|         [50 - 12, 50 - 15, 50 - 21], | ||||
|         [50 - 56, 50 - 73, 50 - 86], | ||||
|         [50 - 52, 50 - 61, 50 - 69], | ||||
|         [50 - 30, 50 - 32, 50], | ||||
|     ], | ||||
|     null, | ||||
|     'B2' | ||||
| ); | ||||
|  | ||||
| @ -6,7 +6,7 @@ use PhpOffice\PhpSpreadsheet\Helper\Sample; | ||||
| 
 | ||||
| error_reporting(E_ALL); | ||||
| 
 | ||||
| require_once __DIR__ . '/../src/Bootstrap.php'; | ||||
| require_once __DIR__ . '/Bootstrap.php'; | ||||
| 
 | ||||
| $helper = new Sample(); | ||||
| 
 | ||||
|  | ||||
| @ -23,7 +23,7 @@ class ChunkReadFilter implements IReadFilter | ||||
|      * @param mixed $startRow | ||||
|      * @param mixed $chunkSize | ||||
|      */ | ||||
|     public function setRows($startRow, $chunkSize) | ||||
|     public function setRows($startRow, $chunkSize): void | ||||
|     { | ||||
|         $this->startRow = $startRow; | ||||
|         $this->endRow = $startRow + $chunkSize; | ||||
|  | ||||
| @ -24,7 +24,7 @@ class ChunkReadFilter implements IReadFilter | ||||
|      * @param mixed $startRow | ||||
|      * @param mixed $chunkSize | ||||
|      */ | ||||
|     public function setRows($startRow, $chunkSize) | ||||
|     public function setRows($startRow, $chunkSize): void | ||||
|     { | ||||
|         $this->startRow = $startRow; | ||||
|         $this->endRow = $startRow + $chunkSize; | ||||
|  | ||||
| @ -12,12 +12,12 @@ $spreadsheet = new Spreadsheet(); | ||||
| $worksheet = $spreadsheet->getActiveSheet(); | ||||
| $worksheet->fromArray( | ||||
|     [ | ||||
|             ['', 2010, 2011, 2012], | ||||
|             ['Q1', 12, 15, 21], | ||||
|             ['Q2', 56, 73, 86], | ||||
|             ['Q3', 52, 61, 69], | ||||
|             ['Q4', 30, 32, 0], | ||||
|         ] | ||||
|         ['', 2010, 2011, 2012], | ||||
|         ['Q1', 12, 15, 21], | ||||
|         ['Q2', 56, 73, 86], | ||||
|         ['Q3', 52, 61, 69], | ||||
|         ['Q4', 30, 32, 0], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Set the Labels for each data series we want to plot
 | ||||
| @ -83,7 +83,7 @@ $chart = new Chart( | ||||
|     $legend, // legend
 | ||||
|     $plotArea, // plotArea
 | ||||
|     true, // plotVisibleOnly
 | ||||
|     0, // displayBlanksAs
 | ||||
|     DataSeries::EMPTY_AS_GAP, // displayBlanksAs
 | ||||
|     null, // xAxisLabel
 | ||||
|     $yAxisLabel  // yAxisLabel
 | ||||
| ); | ||||
|  | ||||
| @ -184,59 +184,59 @@ $spreadsheet->getActiveSheet()->getStyle('A1:E1')->getFill()->getStartColor()->s | ||||
| $helper->log('Set style for header row using alternative method'); | ||||
| $spreadsheet->getActiveSheet()->getStyle('A3:E3')->applyFromArray( | ||||
|     [ | ||||
|             'font' => [ | ||||
|                 'bold' => true, | ||||
|         'font' => [ | ||||
|             'bold' => true, | ||||
|         ], | ||||
|         'alignment' => [ | ||||
|             'horizontal' => Alignment::HORIZONTAL_RIGHT, | ||||
|         ], | ||||
|         'borders' => [ | ||||
|             'top' => [ | ||||
|                 'borderStyle' => Border::BORDER_THIN, | ||||
|             ], | ||||
|             'alignment' => [ | ||||
|                 'horizontal' => Alignment::HORIZONTAL_RIGHT, | ||||
|         ], | ||||
|         'fill' => [ | ||||
|             'fillType' => Fill::FILL_GRADIENT_LINEAR, | ||||
|             'rotation' => 90, | ||||
|             'startColor' => [ | ||||
|                 'argb' => 'FFA0A0A0', | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'top' => [ | ||||
|                     'borderStyle' => Border::BORDER_THIN, | ||||
|                 ], | ||||
|             'endColor' => [ | ||||
|                 'argb' => 'FFFFFFFF', | ||||
|             ], | ||||
|             'fill' => [ | ||||
|                 'fillType' => Fill::FILL_GRADIENT_LINEAR, | ||||
|                 'rotation' => 90, | ||||
|                 'startColor' => [ | ||||
|                     'argb' => 'FFA0A0A0', | ||||
|                 ], | ||||
|                 'endColor' => [ | ||||
|                     'argb' => 'FFFFFFFF', | ||||
|                 ], | ||||
|             ], | ||||
|         ] | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->getStyle('A3')->applyFromArray( | ||||
|     [ | ||||
|             'alignment' => [ | ||||
|                 'horizontal' => Alignment::HORIZONTAL_LEFT, | ||||
|         'alignment' => [ | ||||
|             'horizontal' => Alignment::HORIZONTAL_LEFT, | ||||
|         ], | ||||
|         'borders' => [ | ||||
|             'left' => [ | ||||
|                 'borderStyle' => Border::BORDER_THIN, | ||||
|             ], | ||||
|             'borders' => [ | ||||
|                 'left' => [ | ||||
|                     'borderStyle' => Border::BORDER_THIN, | ||||
|                 ], | ||||
|             ], | ||||
|         ] | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->getStyle('B3')->applyFromArray( | ||||
|     [ | ||||
|             'alignment' => [ | ||||
|                 'horizontal' => Alignment::HORIZONTAL_LEFT, | ||||
|             ], | ||||
|         ] | ||||
|         'alignment' => [ | ||||
|             'horizontal' => Alignment::HORIZONTAL_LEFT, | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| $spreadsheet->getActiveSheet()->getStyle('E3')->applyFromArray( | ||||
|     [ | ||||
|             'borders' => [ | ||||
|                 'right' => [ | ||||
|                     'borderStyle' => Border::BORDER_THIN, | ||||
|                 ], | ||||
|         'borders' => [ | ||||
|             'right' => [ | ||||
|                 'borderStyle' => Border::BORDER_THIN, | ||||
|             ], | ||||
|         ] | ||||
|         ], | ||||
|     ] | ||||
| ); | ||||
| 
 | ||||
| // Unprotect a cell
 | ||||
|  | ||||
| @ -11,6 +11,7 @@ use PhpOffice\PhpSpreadsheet\NamedRange; | ||||
| use PhpOffice\PhpSpreadsheet\Shared; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; | ||||
| use ReflectionMethod; | ||||
| 
 | ||||
| class Calculation | ||||
| { | ||||
| @ -1853,6 +1854,16 @@ class Calculation | ||||
|             'functionCall' => [MathTrig::class, 'SERIESSUM'], | ||||
|             'argumentCount' => '4', | ||||
|         ], | ||||
|         'SHEET' => [ | ||||
|             'category' => Category::CATEGORY_INFORMATION, | ||||
|             'functionCall' => [Functions::class, 'DUMMY'], | ||||
|             'argumentCount' => '0,1', | ||||
|         ], | ||||
|         'SHEETS' => [ | ||||
|             'category' => Category::CATEGORY_INFORMATION, | ||||
|             'functionCall' => [Functions::class, 'DUMMY'], | ||||
|             'argumentCount' => '0,1', | ||||
|         ], | ||||
|         'SIGN' => [ | ||||
|             'category' => Category::CATEGORY_MATH_AND_TRIG, | ||||
|             'functionCall' => [MathTrig::class, 'SIGN'], | ||||
| @ -2247,18 +2258,22 @@ class Calculation | ||||
|             'argumentCount' => '*', | ||||
|             'functionCall' => [__CLASS__, 'mkMatrix'], | ||||
|         ], | ||||
|         'NAME.ERROR' => [ | ||||
|             'argumentCount' => '*', | ||||
|             'functionCall' => [Functions::class, 'NAME'], | ||||
|         ], | ||||
|     ]; | ||||
| 
 | ||||
|     public function __construct(Spreadsheet $spreadsheet = null) | ||||
|     public function __construct(?Spreadsheet $spreadsheet = null) | ||||
|     { | ||||
|         $this->delta = 1 * pow(10, 0 - ini_get('precision')); | ||||
|         $this->delta = 1 * 10 ** (0 - ini_get('precision')); | ||||
| 
 | ||||
|         $this->spreadsheet = $spreadsheet; | ||||
|         $this->cyclicReferenceStack = new CyclicReferenceStack(); | ||||
|         $this->debugLog = new Logger($this->cyclicReferenceStack); | ||||
|     } | ||||
| 
 | ||||
|     private static function loadLocales() | ||||
|     private static function loadLocales(): void | ||||
|     { | ||||
|         $localeFileDirectory = __DIR__ . '/locale/'; | ||||
|         foreach (glob($localeFileDirectory . '*', GLOB_ONLYDIR) as $filename) { | ||||
| @ -2277,7 +2292,7 @@ class Calculation | ||||
|      * | ||||
|      * @return Calculation | ||||
|      */ | ||||
|     public static function getInstance(Spreadsheet $spreadsheet = null) | ||||
|     public static function getInstance(?Spreadsheet $spreadsheet = null) | ||||
|     { | ||||
|         if ($spreadsheet !== null) { | ||||
|             $instance = $spreadsheet->getCalculationEngine(); | ||||
| @ -2297,7 +2312,7 @@ class Calculation | ||||
|      * Flush the calculation cache for any existing instance of this class | ||||
|      *        but only if a Calculation instance exists. | ||||
|      */ | ||||
|     public function flushInstance() | ||||
|     public function flushInstance(): void | ||||
|     { | ||||
|         $this->clearCalculationCache(); | ||||
|         $this->clearBranchStore(); | ||||
| @ -2315,8 +2330,6 @@ class Calculation | ||||
| 
 | ||||
|     /** | ||||
|      * __clone implementation. Cloning should not be allowed in a Singleton! | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     final public function __clone() | ||||
|     { | ||||
| @ -2388,7 +2401,7 @@ class Calculation | ||||
|      * | ||||
|      * @param bool $pValue | ||||
|      */ | ||||
|     public function setCalculationCacheEnabled($pValue) | ||||
|     public function setCalculationCacheEnabled($pValue): void | ||||
|     { | ||||
|         $this->calculationCacheEnabled = $pValue; | ||||
|         $this->clearCalculationCache(); | ||||
| @ -2397,7 +2410,7 @@ class Calculation | ||||
|     /** | ||||
|      * Enable calculation cache. | ||||
|      */ | ||||
|     public function enableCalculationCache() | ||||
|     public function enableCalculationCache(): void | ||||
|     { | ||||
|         $this->setCalculationCacheEnabled(true); | ||||
|     } | ||||
| @ -2405,7 +2418,7 @@ class Calculation | ||||
|     /** | ||||
|      * Disable calculation cache. | ||||
|      */ | ||||
|     public function disableCalculationCache() | ||||
|     public function disableCalculationCache(): void | ||||
|     { | ||||
|         $this->setCalculationCacheEnabled(false); | ||||
|     } | ||||
| @ -2413,7 +2426,7 @@ class Calculation | ||||
|     /** | ||||
|      * Clear calculation cache. | ||||
|      */ | ||||
|     public function clearCalculationCache() | ||||
|     public function clearCalculationCache(): void | ||||
|     { | ||||
|         $this->calculationCache = []; | ||||
|     } | ||||
| @ -2423,7 +2436,7 @@ class Calculation | ||||
|      * | ||||
|      * @param string $worksheetName | ||||
|      */ | ||||
|     public function clearCalculationCacheForWorksheet($worksheetName) | ||||
|     public function clearCalculationCacheForWorksheet($worksheetName): void | ||||
|     { | ||||
|         if (isset($this->calculationCache[$worksheetName])) { | ||||
|             unset($this->calculationCache[$worksheetName]); | ||||
| @ -2436,7 +2449,7 @@ class Calculation | ||||
|      * @param string $fromWorksheetName | ||||
|      * @param string $toWorksheetName | ||||
|      */ | ||||
|     public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName) | ||||
|     public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName): void | ||||
|     { | ||||
|         if (isset($this->calculationCache[$fromWorksheetName])) { | ||||
|             $this->calculationCache[$toWorksheetName] = &$this->calculationCache[$fromWorksheetName]; | ||||
| @ -2447,25 +2460,24 @@ class Calculation | ||||
|     /** | ||||
|      * Enable/disable calculation cache. | ||||
|      * | ||||
|      * @param bool $pValue | ||||
|      * @param mixed $enabled | ||||
|      */ | ||||
|     public function setBranchPruningEnabled($enabled) | ||||
|     public function setBranchPruningEnabled($enabled): void | ||||
|     { | ||||
|         $this->branchPruningEnabled = $enabled; | ||||
|     } | ||||
| 
 | ||||
|     public function enableBranchPruning() | ||||
|     public function enableBranchPruning(): void | ||||
|     { | ||||
|         $this->setBranchPruningEnabled(true); | ||||
|     } | ||||
| 
 | ||||
|     public function disableBranchPruning() | ||||
|     public function disableBranchPruning(): void | ||||
|     { | ||||
|         $this->setBranchPruningEnabled(false); | ||||
|     } | ||||
| 
 | ||||
|     public function clearBranchStore() | ||||
|     public function clearBranchStore(): void | ||||
|     { | ||||
|         $this->branchStoreKeyCounter = 0; | ||||
|     } | ||||
| @ -2765,11 +2777,9 @@ class Calculation | ||||
|      * | ||||
|      * @param Cell $pCell Cell to calculate | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function calculate(Cell $pCell = null) | ||||
|     public function calculate(?Cell $pCell = null) | ||||
|     { | ||||
|         try { | ||||
|             return $this->calculateCellValue($pCell); | ||||
| @ -2784,11 +2794,9 @@ class Calculation | ||||
|      * @param Cell $pCell Cell to calculate | ||||
|      * @param bool $resetLog Flag indicating whether the debug log should be reset or not | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function calculateCellValue(Cell $pCell = null, $resetLog = true) | ||||
|     public function calculateCellValue(?Cell $pCell = null, $resetLog = true) | ||||
|     { | ||||
|         if ($pCell === null) { | ||||
|             return null; | ||||
| @ -2888,11 +2896,9 @@ class Calculation | ||||
|      * @param string $cellID Address of the cell to calculate | ||||
|      * @param Cell $pCell Cell to calculate | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function calculateFormula($formula, $cellID = null, Cell $pCell = null) | ||||
|     public function calculateFormula($formula, $cellID = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         //    Initialise the logging settings
 | ||||
|         $this->formulaError = null; | ||||
| @ -2951,7 +2957,7 @@ class Calculation | ||||
|      * @param string $cellReference | ||||
|      * @param mixed $cellValue | ||||
|      */ | ||||
|     public function saveValueToCache($cellReference, $cellValue) | ||||
|     public function saveValueToCache($cellReference, $cellValue): void | ||||
|     { | ||||
|         if ($this->calculationCacheEnabled) { | ||||
|             $this->calculationCache[$cellReference] = $cellValue; | ||||
| @ -2965,11 +2971,9 @@ class Calculation | ||||
|      * @param string $cellID The ID (e.g. A3) of the cell that we are calculating | ||||
|      * @param Cell $pCell Cell to calculate | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function _calculateFormulaValue($formula, $cellID = null, Cell $pCell = null) | ||||
|     public function _calculateFormulaValue($formula, $cellID = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         $cellValue = null; | ||||
| 
 | ||||
| @ -3115,7 +3119,7 @@ class Calculation | ||||
|      * @param int $matrix2Rows Row size of second matrix operand | ||||
|      * @param int $matrix2Columns Column size of second matrix operand | ||||
|      */ | ||||
|     private static function resizeMatricesShrink(&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns) | ||||
|     private static function resizeMatricesShrink(&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns): void | ||||
|     { | ||||
|         if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { | ||||
|             if ($matrix2Rows < $matrix1Rows) { | ||||
| @ -3158,7 +3162,7 @@ class Calculation | ||||
|      * @param int $matrix2Rows Row size of second matrix operand | ||||
|      * @param int $matrix2Columns Column size of second matrix operand | ||||
|      */ | ||||
|     private static function resizeMatricesExtend(&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns) | ||||
|     private static function resizeMatricesExtend(&$matrix1, &$matrix2, $matrix1Rows, $matrix1Columns, $matrix2Rows, $matrix2Columns): void | ||||
|     { | ||||
|         if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { | ||||
|             if ($matrix2Columns < $matrix1Columns) { | ||||
| @ -3367,11 +3371,10 @@ class Calculation | ||||
| 
 | ||||
|     /** | ||||
|      * @param string $formula | ||||
|      * @param null|\PhpOffice\PhpSpreadsheet\Cell\Cell $pCell | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function _parseFormula($formula, Cell $pCell = null) | ||||
|     private function _parseFormula($formula, ?Cell $pCell = null) | ||||
|     { | ||||
|         if (($formula = $this->convertMatrixReferences(trim($formula))) === false) { | ||||
|             return false; | ||||
| @ -3465,7 +3468,7 @@ class Calculation | ||||
|                 ++$index; //    Drop the redundant plus symbol
 | ||||
|             } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) {    //    We have to explicitly deny a tilde or pipe, because they are legal
 | ||||
|                 return $this->raiseFormulaError("Formula Error: Illegal character '~'"); //        on the stack but not in the input expression
 | ||||
|             } elseif ((isset(self::$operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) {    //    Are we putting an operator on the stack?
 | ||||
|             } elseif ((isset(self::$operators[$opCharacter]) || $isOperandOrFunction) && $expectingOperator) {    //    Are we putting an operator on the stack?
 | ||||
|                 while ($stack->count() > 0 && | ||||
|                     ($o2 = $stack->last()) && | ||||
|                     isset(self::$operators[$o2['value']]) && | ||||
| @ -3491,7 +3494,7 @@ class Calculation | ||||
|                 // Branch pruning we decrease the depth whether is it a function
 | ||||
|                 // call or a parenthesis
 | ||||
|                 if (!empty($pendingStoreKey)) { | ||||
|                     $parenthesisDepthMap[$pendingStoreKey] -= 1; | ||||
|                     --$parenthesisDepthMap[$pendingStoreKey]; | ||||
|                 } | ||||
| 
 | ||||
|                 if (is_array($d) && preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) {    //    Did this parenthesis just close a function?
 | ||||
| @ -3505,7 +3508,7 @@ class Calculation | ||||
|                         } | ||||
|                         $expectingThenMap[$pendingStoreKey] = false; | ||||
|                         $expectingElseMap[$pendingStoreKey] = false; | ||||
|                         $parenthesisDepthMap[$pendingStoreKey] -= 1; | ||||
|                         --$parenthesisDepthMap[$pendingStoreKey]; | ||||
|                         array_pop($pendingStoreKeysStack); | ||||
|                         unset($pendingStoreKey); | ||||
|                     } | ||||
| @ -3611,7 +3614,7 @@ class Calculation | ||||
|                 ++$index; | ||||
|             } elseif ($opCharacter == '(' && !$expectingOperator) { | ||||
|                 if (!empty($pendingStoreKey)) { // Branch pruning: we go deeper
 | ||||
|                     $parenthesisDepthMap[$pendingStoreKey] += 1; | ||||
|                     ++$parenthesisDepthMap[$pendingStoreKey]; | ||||
|                 } | ||||
|                 $stack->push('Brace', '(', null, $currentCondition, $currentOnlyIf, $currentOnlyIf); | ||||
|                 ++$index; | ||||
| @ -3625,33 +3628,33 @@ class Calculation | ||||
|                     $val = preg_replace('/\s/u', '', $val); | ||||
|                     if (isset(self::$phpSpreadsheetFunctions[strtoupper($matches[1])]) || isset(self::$controlFunctions[strtoupper($matches[1])])) {    // it's a function
 | ||||
|                         $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 ' . $valToUpper . ')', 0, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); | ||||
|                             $expectingOperator = true; | ||||
|                         } else { | ||||
|                             $stack->push('Operand Count for Function ' . $valToUpper . ')', 1, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); | ||||
|                             $expectingOperator = false; | ||||
|                         } | ||||
|                         $stack->push('Brace', '('); | ||||
|                     } else {    // it's a var w/ implicit multiplication
 | ||||
|                         $output[] = ['type' => 'Value', 'value' => $matches[1], 'reference' => null]; | ||||
|                     } else { | ||||
|                         $valToUpper = 'NAME.ERROR('; | ||||
|                     } | ||||
|                     // 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 an if but we go deeper
 | ||||
|                         if (!empty($pendingStoreKey) && array_key_exists($pendingStoreKey, $parenthesisDepthMap)) { | ||||
|                             ++$parenthesisDepthMap[$pendingStoreKey]; | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     $stack->push('Function', $valToUpper, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); | ||||
|                     // tests if the function is closed right after opening
 | ||||
|                     $ax = preg_match('/^\s*\)/u', substr($formula, $index + $length)); | ||||
|                     if ($ax) { | ||||
|                         $stack->push('Operand Count for Function ' . $valToUpper . ')', 0, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); | ||||
|                         $expectingOperator = true; | ||||
|                     } else { | ||||
|                         $stack->push('Operand Count for Function ' . $valToUpper . ')', 1, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot); | ||||
|                         $expectingOperator = false; | ||||
|                     } | ||||
|                     $stack->push('Brace', '('); | ||||
|                 } elseif (preg_match('/^' . self::CALCULATION_REGEXP_CELLREF . '$/i', $val, $matches)) { | ||||
|                     //    Watch for this case-change when modifying to allow cell references in different worksheets...
 | ||||
|                     //    Should only be applied to the actual cell column, not the worksheet name
 | ||||
| @ -3814,11 +3817,10 @@ class Calculation | ||||
|     /** | ||||
|      * @param mixed $tokens | ||||
|      * @param null|string $cellID | ||||
|      * @param null|Cell $pCell | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function processTokenStack($tokens, $cellID = null, Cell $pCell = null) | ||||
|     private function processTokenStack($tokens, $cellID = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         if ($tokens == false) { | ||||
|             return false; | ||||
| @ -4357,7 +4359,6 @@ class Calculation | ||||
|      * @param mixed $operand1 | ||||
|      * @param mixed $operand2 | ||||
|      * @param string $operation | ||||
|      * @param Stack $stack | ||||
|      * @param bool $recursingArrays | ||||
|      * | ||||
|      * @return mixed | ||||
| @ -4579,7 +4580,7 @@ class Calculation | ||||
|                         break; | ||||
|                     //    Power
 | ||||
|                     case '^': | ||||
|                         $result = pow($operand1, $operand2); | ||||
|                         $result = $operand1 ** $operand2; | ||||
| 
 | ||||
|                         break; | ||||
|                 } | ||||
| @ -4616,7 +4617,7 @@ class Calculation | ||||
|      * | ||||
|      * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. | ||||
|      */ | ||||
|     public function extractCellRange(&$pRange = 'A1', Worksheet $pSheet = null, $resetLog = true) | ||||
|     public function extractCellRange(&$pRange = 'A1', ?Worksheet $pSheet = null, $resetLog = true) | ||||
|     { | ||||
|         // Return value
 | ||||
|         $returnValue = []; | ||||
| @ -4669,7 +4670,7 @@ class Calculation | ||||
|      * | ||||
|      * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. | ||||
|      */ | ||||
|     public function extractNamedRange(&$pRange = 'A1', Worksheet $pSheet = null, $resetLog = true) | ||||
|     public function extractNamedRange(&$pRange = 'A1', ?Worksheet $pSheet = null, $resetLog = true) | ||||
|     { | ||||
|         // Return value
 | ||||
|         $returnValue = []; | ||||
| @ -4769,21 +4770,19 @@ class Calculation | ||||
|     /** | ||||
|      * Add cell reference if needed while making sure that it is the last argument. | ||||
|      * | ||||
|      * @param array $args | ||||
|      * @param bool $passCellReference | ||||
|      * @param array|string $functionCall | ||||
|      * @param null|Cell $pCell | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function addCellReference(array $args, $passCellReference, $functionCall, Cell $pCell = null) | ||||
|     private function addCellReference(array $args, $passCellReference, $functionCall, ?Cell $pCell = null) | ||||
|     { | ||||
|         if ($passCellReference) { | ||||
|             if (is_array($functionCall)) { | ||||
|                 $className = $functionCall[0]; | ||||
|                 $methodName = $functionCall[1]; | ||||
| 
 | ||||
|                 $reflectionMethod = new \ReflectionMethod($className, $methodName); | ||||
|                 $reflectionMethod = new ReflectionMethod($className, $methodName); | ||||
|                 $argumentCount = count($reflectionMethod->getParameters()); | ||||
|                 while (count($args) < $argumentCount - 1) { | ||||
|                     $args[] = null; | ||||
|  | ||||
| @ -130,8 +130,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DAVERAGE(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -174,8 +172,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DAVERAGE(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -217,8 +213,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DCOUNTA(database,[field],criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -269,8 +263,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DGET(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -313,8 +305,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DMAX(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -354,8 +344,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DMIN(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -394,8 +382,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DPRODUCT(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -435,8 +421,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DSTDEV(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -476,8 +460,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DSTDEVP(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -516,8 +498,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DSUM(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -557,8 +537,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DVAR(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
| @ -598,8 +576,6 @@ class Database | ||||
|      * Excel Function: | ||||
|      *        DVARP(database,field,criteria) | ||||
|      * | ||||
|      * @category Database Functions | ||||
|      * | ||||
|      * @param mixed[] $database The range of cells that makes up the list or database. | ||||
|      *                                        A database is a list of related data in which rows of related | ||||
|      *                                        information are records, and columns of data are fields. The | ||||
|  | ||||
| @ -2,6 +2,8 @@ | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Calculation; | ||||
| 
 | ||||
| use DateTimeImmutable; | ||||
| use DateTimeInterface; | ||||
| use PhpOffice\PhpSpreadsheet\Shared\Date; | ||||
| use PhpOffice\PhpSpreadsheet\Shared\StringHelper; | ||||
| 
 | ||||
| @ -59,18 +61,14 @@ class DateTime | ||||
|     /** | ||||
|      * getDateValue. | ||||
|      * | ||||
|      * @param string $dateValue | ||||
|      * @param mixed $dateValue | ||||
|      * | ||||
|      * @return mixed Excel date/time serial value, or string if error | ||||
|      */ | ||||
|     public static function getDateValue($dateValue) | ||||
|     { | ||||
|         if (!is_numeric($dateValue)) { | ||||
|             if ((is_string($dateValue)) && | ||||
|                 (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) { | ||||
|                 return Functions::VALUE(); | ||||
|             } | ||||
|             if ((is_object($dateValue)) && ($dateValue instanceof \DateTimeInterface)) { | ||||
|             if ((is_object($dateValue)) && ($dateValue instanceof DateTimeInterface)) { | ||||
|                 $dateValue = Date::PHPToExcel($dateValue); | ||||
|             } else { | ||||
|                 $saveReturnDateType = Functions::getReturnDateType(); | ||||
| @ -141,8 +139,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        NOW() | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, | ||||
|      *                        depending on the value of the ReturnDateType flag | ||||
|      */ | ||||
| @ -184,8 +180,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        TODAY() | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, | ||||
|      *                        depending on the value of the ReturnDateType flag | ||||
|      */ | ||||
| @ -229,8 +223,6 @@ class DateTime | ||||
|      * A Month name or abbreviation (English only at this point) such as 'January' or 'Jan' will still be accepted, | ||||
|      *     as will a day value with a suffix (e.g. '21st' rather than simply 21); again only English language. | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param int $year The value of the year argument can include one to four digits. | ||||
|      *                                Excel interprets the year argument according to the configured | ||||
|      *                                date system: 1900 or 1904. | ||||
| @ -343,8 +335,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        TIME(hour,minute,second) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param int $hour A number from 0 (zero) to 32767 representing the hour. | ||||
|      *                                    Any value greater than 23 will be divided by 24 and the remainder | ||||
|      *                                    will be treated as the hour value. For example, TIME(27,0,0) = | ||||
| @ -456,8 +446,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        DATEVALUE(dateValue) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param string $dateValue Text that represents a date in a Microsoft Excel date format. | ||||
|      *                                    For example, "1/30/2008" or "30-Jan-2008" are text strings within | ||||
|      *                                    quotation marks that represent dates. Using the default date | ||||
| @ -591,8 +579,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        TIMEVALUE(timeValue) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param string $timeValue A text string that represents a time in any one of the Microsoft | ||||
|      *                                    Excel time formats; for example, "6:45 PM" and "18:45" text strings | ||||
|      *                                    within quotation marks that represent time. | ||||
| @ -770,11 +756,9 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        DAYS(endDate, startDate) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param \DateTimeImmutable|float|int|string $endDate Excel date serial value (float), | ||||
|      * @param DateTimeImmutable|float|int|string $endDate Excel date serial value (float), | ||||
|      * PHP date timestamp (integer), PHP DateTime object, or a standard date string | ||||
|      * @param \DateTimeImmutable|float|int|string $startDate Excel date serial value (float), | ||||
|      * @param DateTimeImmutable|float|int|string $startDate Excel date serial value (float), | ||||
|      * PHP date timestamp (integer), PHP DateTime object, or a standard date string | ||||
|      * | ||||
|      * @return int|string Number of days between start date and end date or an error | ||||
| @ -818,8 +802,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        DAYS360(startDate,endDate[,method]) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), | ||||
|      *                                        PHP DateTime object, or a standard date string | ||||
|      * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), | ||||
| @ -881,8 +863,6 @@ class DateTime | ||||
|      * See https://lists.oasis-open.org/archives/office-formula/200806/msg00039.html | ||||
|      *     for description of algorithm used in Excel | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), | ||||
|      *                                    PHP DateTime object, or a standard date string | ||||
|      * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), | ||||
| @ -983,8 +963,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        NETWORKDAYS(startDate,endDate[,holidays[,holiday[,...]]]) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), | ||||
|      *                                            PHP DateTime object, or a standard date string | ||||
|      * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), | ||||
| @ -1063,8 +1041,6 @@ class DateTime | ||||
|      * Excel Function: | ||||
|      *        WORKDAY(startDate,endDays[,holidays[,holiday[,...]]]) | ||||
|      * | ||||
|      * @category Date/Time Functions | ||||
|      * | ||||
|      * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), | ||||
|      *                                        PHP DateTime object, or a standard date string | ||||
|      * @param int $endDays The number of nonweekend and nonholiday days before or after | ||||
| @ -1305,7 +1281,7 @@ class DateTime | ||||
|         self::DOW_SATURDAY, | ||||
|         self::DOW_SUNDAY, | ||||
|         self::STARTWEEK_MONDAY_ISO => self::STARTWEEK_MONDAY_ISO, | ||||
|         ]; | ||||
|     ]; | ||||
| 
 | ||||
|     /** | ||||
|      * WEEKNUM. | ||||
|  | ||||
| @ -26,7 +26,7 @@ class CyclicReferenceStack | ||||
|      * | ||||
|      * @param mixed $value | ||||
|      */ | ||||
|     public function push($value) | ||||
|     public function push($value): void | ||||
|     { | ||||
|         $this->stack[$value] = $value; | ||||
|     } | ||||
| @ -56,7 +56,7 @@ class CyclicReferenceStack | ||||
|     /** | ||||
|      * Clear the stack. | ||||
|      */ | ||||
|     public function clear() | ||||
|     public function clear(): void | ||||
|     { | ||||
|         $this->stack = []; | ||||
|     } | ||||
|  | ||||
| @ -39,8 +39,6 @@ class Logger | ||||
| 
 | ||||
|     /** | ||||
|      * Instantiate a Calculation engine logger. | ||||
|      * | ||||
|      * @param CyclicReferenceStack $stack | ||||
|      */ | ||||
|     public function __construct(CyclicReferenceStack $stack) | ||||
|     { | ||||
| @ -52,7 +50,7 @@ class Logger | ||||
|      * | ||||
|      * @param bool $pValue | ||||
|      */ | ||||
|     public function setWriteDebugLog($pValue) | ||||
|     public function setWriteDebugLog($pValue): void | ||||
|     { | ||||
|         $this->writeDebugLog = $pValue; | ||||
|     } | ||||
| @ -72,7 +70,7 @@ class Logger | ||||
|      * | ||||
|      * @param bool $pValue | ||||
|      */ | ||||
|     public function setEchoDebugLog($pValue) | ||||
|     public function setEchoDebugLog($pValue): void | ||||
|     { | ||||
|         $this->echoDebugLog = $pValue; | ||||
|     } | ||||
| @ -90,11 +88,11 @@ class Logger | ||||
|     /** | ||||
|      * Write an entry to the calculation engine debug log. | ||||
|      */ | ||||
|     public function writeDebugLog(...$args) | ||||
|     public function writeDebugLog(...$args): void | ||||
|     { | ||||
|         //    Only write the debug log if logging is enabled
 | ||||
|         if ($this->writeDebugLog) { | ||||
|             $message = implode($args); | ||||
|             $message = implode('', $args); | ||||
|             $cellReference = implode(' -> ', $this->cellStack->showStack()); | ||||
|             if ($this->echoDebugLog) { | ||||
|                 echo $cellReference, | ||||
| @ -111,7 +109,7 @@ class Logger | ||||
|     /** | ||||
|      * Clear the calculation engine debug log. | ||||
|      */ | ||||
|     public function clearLog() | ||||
|     public function clearLog(): void | ||||
|     { | ||||
|         $this->debugLog = []; | ||||
|     } | ||||
|  | ||||
| @ -776,8 +776,6 @@ class Engineering | ||||
|      *    Excel Function: | ||||
|      *        BESSELI(x,ord) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param float $x The value at which to evaluate the function. | ||||
|      *                                If x is nonnumeric, BESSELI returns the #VALUE! error value.
 | ||||
|      * @param int $ord The order of the Bessel function. | ||||
| @ -799,7 +797,7 @@ class Engineering | ||||
|             } | ||||
| 
 | ||||
|             if (abs($x) <= 30) { | ||||
|                 $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord); | ||||
|                 $fResult = $fTerm = ($x / 2) ** $ord / MathTrig::FACT($ord); | ||||
|                 $ordK = 1; | ||||
|                 $fSqrX = ($x * $x) / 4; | ||||
|                 do { | ||||
| @ -831,8 +829,6 @@ class Engineering | ||||
|      *    Excel Function: | ||||
|      *        BESSELJ(x,ord) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param float $x The value at which to evaluate the function. | ||||
|      *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
 | ||||
|      * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. | ||||
| @ -854,7 +850,7 @@ class Engineering | ||||
| 
 | ||||
|             $fResult = 0; | ||||
|             if (abs($x) <= 30) { | ||||
|                 $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord); | ||||
|                 $fResult = $fTerm = ($x / 2) ** $ord / MathTrig::FACT($ord); | ||||
|                 $ordK = 1; | ||||
|                 $fSqrX = ($x * $x) / -4; | ||||
|                 do { | ||||
| @ -924,8 +920,6 @@ class Engineering | ||||
|      *    Excel Function: | ||||
|      *        BESSELK(x,ord) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param float $x The value at which to evaluate the function. | ||||
|      *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
 | ||||
|      * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. | ||||
| @ -1013,8 +1007,6 @@ class Engineering | ||||
|      *    Excel Function: | ||||
|      *        BESSELY(x,ord) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param float $x The value at which to evaluate the function. | ||||
|      *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
 | ||||
|      * @param int $ord The order of the Bessel function. If n is not an integer, it is truncated. | ||||
| @ -1067,8 +1059,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BIN2DEC(x) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The binary number (as a string) that you want to convert. The number | ||||
|      *                                cannot contain more than 10 characters (10 bits). The most significant | ||||
|      *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits. | ||||
| @ -1116,8 +1106,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BIN2HEX(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The binary number (as a string) that you want to convert. The number | ||||
|      *                                cannot contain more than 10 characters (10 bits). The most significant | ||||
|      *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits. | ||||
| @ -1172,8 +1160,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BIN2OCT(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The binary number (as a string) that you want to convert. The number | ||||
|      *                                cannot contain more than 10 characters (10 bits). The most significant | ||||
|      *                                bit of number is the sign bit. The remaining 9 bits are magnitude bits. | ||||
| @ -1227,8 +1213,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        DEC2BIN(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The decimal integer you want to convert. If number is negative, | ||||
|      *                                valid place values are ignored and DEC2BIN returns a 10-character | ||||
|      *                                (10-bit) binary number in which the most significant bit is the sign | ||||
| @ -1288,8 +1272,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        DEC2HEX(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The decimal integer you want to convert. If number is negative, | ||||
|      *                                places is ignored and DEC2HEX returns a 10-character (40-bit) | ||||
|      *                                hexadecimal number in which the most significant bit is the sign | ||||
| @ -1343,8 +1325,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        DEC2OCT(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The decimal integer you want to convert. If number is negative, | ||||
|      *                                places is ignored and DEC2OCT returns a 10-character (30-bit) | ||||
|      *                                octal number in which the most significant bit is the sign bit. | ||||
| @ -1399,8 +1379,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        HEX2BIN(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x the hexadecimal number you want to convert. | ||||
|      *                  Number cannot contain more than 10 characters. | ||||
|      *                  The most significant bit of number is the sign bit (40th bit from the right). | ||||
| @ -1444,8 +1422,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        HEX2DEC(x) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The hexadecimal number you want to convert. This number cannot | ||||
|      *                                contain more than 10 characters (40 bits). The most significant | ||||
|      *                                bit of number is the sign bit. The remaining 39 bits are magnitude | ||||
| @ -1495,8 +1471,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        HEX2OCT(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The hexadecimal number you want to convert. Number cannot | ||||
|      *                                    contain more than 10 characters. The most significant bit of | ||||
|      *                                    number is the sign bit. The remaining 39 bits are magnitude | ||||
| @ -1549,8 +1523,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        OCT2BIN(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The octal number you want to convert. Number may not | ||||
|      *                                    contain more than 10 characters. The most significant | ||||
|      *                                    bit of number is the sign bit. The remaining 29 bits | ||||
| @ -1600,8 +1572,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        OCT2DEC(x) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The octal number you want to convert. Number may not contain | ||||
|      *                                more than 10 octal characters (30 bits). The most significant | ||||
|      *                                bit of number is the sign bit. The remaining 29 bits are | ||||
| @ -1646,8 +1616,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        OCT2HEX(x[,places]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $x The octal number you want to convert. Number may not contain | ||||
|      *                                    more than 10 octal characters (30 bits). The most significant | ||||
|      *                                    bit of number is the sign bit. The remaining 29 bits are | ||||
| @ -1693,8 +1661,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        COMPLEX(realNumber,imaginary[,suffix]) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param float $realNumber the real coefficient of the complex number | ||||
|      * @param float $imaginary the imaginary coefficient of the complex number | ||||
|      * @param string $suffix The suffix for the imaginary component of the complex number. | ||||
| @ -1727,8 +1693,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        IMAGINARY(complexNumber) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $complexNumber the complex number for which you want the imaginary | ||||
|      *                                         coefficient | ||||
|      * | ||||
| @ -1749,8 +1713,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        IMREAL(complexNumber) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param string $complexNumber the complex number for which you want the real coefficient | ||||
|      * | ||||
|      * @return float | ||||
| @ -2346,8 +2308,6 @@ class Engineering | ||||
|      * | ||||
|      * @param mixed $value | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     private static function validateBitwiseArgument($value) | ||||
| @ -2359,7 +2319,7 @@ class Engineering | ||||
|         } elseif (is_numeric($value)) { | ||||
|             if ($value == (int) ($value)) { | ||||
|                 $value = (int) ($value); | ||||
|                 if (($value > pow(2, 48) - 1) || ($value < 0)) { | ||||
|                 if (($value > 2 ** 48 - 1) || ($value < 0)) { | ||||
|                     throw new Exception(Functions::NAN()); | ||||
|                 } | ||||
| 
 | ||||
| @ -2380,8 +2340,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BITAND(number1, number2) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param int $number1 | ||||
|      * @param int $number2 | ||||
|      * | ||||
| @ -2407,8 +2365,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BITOR(number1, number2) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param int $number1 | ||||
|      * @param int $number2 | ||||
|      * | ||||
| @ -2434,8 +2390,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BITXOR(number1, number2) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param int $number1 | ||||
|      * @param int $number2 | ||||
|      * | ||||
| @ -2461,8 +2415,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BITLSHIFT(number, shift_amount) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param int $number | ||||
|      * @param int $shiftAmount | ||||
|      * | ||||
| @ -2479,7 +2431,7 @@ class Engineering | ||||
|         $shiftAmount = Functions::flattenSingleValue($shiftAmount); | ||||
| 
 | ||||
|         $result = $number << $shiftAmount; | ||||
|         if ($result > pow(2, 48) - 1) { | ||||
|         if ($result > 2 ** 48 - 1) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
| @ -2494,8 +2446,6 @@ class Engineering | ||||
|      * Excel Function: | ||||
|      *        BITRSHIFT(number, shift_amount) | ||||
|      * | ||||
|      * @category Engineering Functions | ||||
|      * | ||||
|      * @param int $number | ||||
|      * @param int $shiftAmount | ||||
|      * | ||||
|  | ||||
| @ -15,7 +15,7 @@ class Exception extends PhpSpreadsheetException | ||||
|      * @param mixed $line | ||||
|      * @param mixed $context | ||||
|      */ | ||||
|     public static function errorHandlerCallback($code, $string, $file, $line, $context) | ||||
|     public static function errorHandlerCallback($code, $string, $file, $line, $context): void | ||||
|     { | ||||
|         $e = new self($string, $code); | ||||
|         $e->line = $line; | ||||
|  | ||||
| @ -6,7 +6,7 @@ use PhpOffice\PhpSpreadsheet\Shared\Date; | ||||
| 
 | ||||
| class Financial | ||||
| { | ||||
|     const FINANCIAL_MAX_ITERATIONS = 32; | ||||
|     const FINANCIAL_MAX_ITERATIONS = 128; | ||||
| 
 | ||||
|     const FINANCIAL_PRECISION = 1.0e-08; | ||||
| 
 | ||||
| @ -50,10 +50,6 @@ class Financial | ||||
|         if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) { | ||||
|             return true; | ||||
|         } | ||||
|         if ((Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) && | ||||
|             (($frequency == 6) || ($frequency == 12))) { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| @ -118,8 +114,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        ACCRINT(issue,firstinterest,settlement,rate,par,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $issue the security's issue date | ||||
|      * @param mixed $firstinterest the security's first interest date | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
| @ -133,10 +127,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -183,8 +173,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        ACCRINTM(issue,settlement,rate[,par[,basis]]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $issue The security's issue date | ||||
|      * @param mixed $settlement The security's settlement (or maturity) date | ||||
|      * @param float $rate The security's annual coupon rate | ||||
| @ -241,8 +229,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        AMORDEGRC(cost,purchased,firstPeriod,salvage,period,rate[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $cost The cost of the asset | ||||
|      * @param mixed $purchased Date of the purchase of the asset | ||||
|      * @param mixed $firstPeriod Date of the end of the first period | ||||
| @ -319,8 +305,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        AMORLINC(cost,purchased,firstPeriod,salvage,period,rate[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $cost The cost of the asset | ||||
|      * @param mixed $purchased Date of the purchase of the asset | ||||
|      * @param mixed $firstPeriod Date of the end of the first period | ||||
| @ -378,8 +362,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPDAYBS(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -390,10 +372,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -426,6 +404,10 @@ class Financial | ||||
|         $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); | ||||
|         $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, false); | ||||
| 
 | ||||
|         if ($basis == 1) { | ||||
|             return abs(DateTime::DAYS($prev, $settlement)); | ||||
|         } | ||||
| 
 | ||||
|         return DateTime::YEARFRAC($prev, $settlement, $basis) * $daysPerYear; | ||||
|     } | ||||
| 
 | ||||
| @ -437,8 +419,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPDAYS(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -449,10 +429,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -511,8 +487,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPDAYSNC(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -523,10 +497,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -570,8 +540,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPNCD(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -582,10 +550,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -628,8 +592,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPNUM(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -640,10 +602,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -673,19 +631,9 @@ class Financial | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis); | ||||
|         $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * $daysPerYear; | ||||
|         $yearsBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, 0); | ||||
| 
 | ||||
|         switch ($frequency) { | ||||
|             case 1: // annual payments
 | ||||
|             case 2: // half-yearly
 | ||||
|             case 4: // quarterly
 | ||||
|             case 6: // bimonthly
 | ||||
|             case 12: // monthly
 | ||||
|                 return ceil($daysBetweenSettlementAndMaturity / $daysPerYear * $frequency); | ||||
|         } | ||||
| 
 | ||||
|         return Functions::VALUE(); | ||||
|         return ceil($yearsBetweenSettlementAndMaturity * $frequency); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -696,8 +644,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        COUPPCD(settlement,maturity,frequency[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -708,10 +654,6 @@ class Financial | ||||
|      *                                        1    Annual | ||||
|      *                                        2    Semi-Annual | ||||
|      *                                        4    Quarterly | ||||
|      *                                    If working in Gnumeric Mode, the following frequency options are | ||||
|      *                                    also available | ||||
|      *                                        6    Bimonthly | ||||
|      *                                        12    Monthly | ||||
|      * @param int $basis The type of day count to use. | ||||
|      *                                        0 or omitted    US (NASD) 30/360 | ||||
|      *                                        1                Actual/actual | ||||
| @ -753,8 +695,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        CUMIPMT(rate,nper,pv,start,end[,type]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $rate The Interest rate | ||||
|      * @param int $nper The total number of payment periods | ||||
|      * @param float $pv Present Value | ||||
| @ -801,8 +741,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        CUMPRINC(rate,nper,pv,start,end[,type]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $rate The Interest rate | ||||
|      * @param int $nper The total number of payment periods | ||||
|      * @param float $pv Present Value | ||||
| @ -854,8 +792,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        DB(cost,salvage,life,period[,month]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $cost Initial cost of the asset | ||||
|      * @param float $salvage Value at the end of the depreciation. | ||||
|      *                                (Sometimes called the salvage value of the asset) | ||||
| @ -889,11 +825,12 @@ class Financial | ||||
|                 return Functions::NAN(); | ||||
|             } | ||||
|             //    Set Fixed Depreciation Rate
 | ||||
|             $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); | ||||
|             $fixedDepreciationRate = 1 - ($salvage / $cost) ** (1 / $life); | ||||
|             $fixedDepreciationRate = round($fixedDepreciationRate, 3); | ||||
| 
 | ||||
|             //    Loop through each period calculating the depreciation
 | ||||
|             $previousDepreciation = 0; | ||||
|             $depreciation = 0; | ||||
|             for ($per = 1; $per <= $period; ++$per) { | ||||
|                 if ($per == 1) { | ||||
|                     $depreciation = $cost * $fixedDepreciationRate * $month / 12; | ||||
| @ -904,9 +841,6 @@ class Financial | ||||
|                 } | ||||
|                 $previousDepreciation += $depreciation; | ||||
|             } | ||||
|             if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { | ||||
|                 $depreciation = round($depreciation, 2); | ||||
|             } | ||||
| 
 | ||||
|             return $depreciation; | ||||
|         } | ||||
| @ -923,8 +857,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        DDB(cost,salvage,life,period[,factor]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $cost Initial cost of the asset | ||||
|      * @param float $salvage Value at the end of the depreciation. | ||||
|      *                                (Sometimes called the salvage value of the asset) | ||||
| @ -957,18 +889,16 @@ class Financial | ||||
|                 return Functions::NAN(); | ||||
|             } | ||||
|             //    Set Fixed Depreciation Rate
 | ||||
|             $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); | ||||
|             $fixedDepreciationRate = 1 - ($salvage / $cost) ** (1 / $life); | ||||
|             $fixedDepreciationRate = round($fixedDepreciationRate, 3); | ||||
| 
 | ||||
|             //    Loop through each period calculating the depreciation
 | ||||
|             $previousDepreciation = 0; | ||||
|             $depreciation = 0; | ||||
|             for ($per = 1; $per <= $period; ++$per) { | ||||
|                 $depreciation = min(($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation)); | ||||
|                 $previousDepreciation += $depreciation; | ||||
|             } | ||||
|             if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) { | ||||
|                 $depreciation = round($depreciation, 2); | ||||
|             } | ||||
| 
 | ||||
|             return $depreciation; | ||||
|         } | ||||
| @ -984,8 +914,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        DISC(settlement,maturity,price,redemption[,basis]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param mixed $settlement The security's settlement date. | ||||
|      *                                The security settlement date is the date after the issue | ||||
|      *                                date when the security is traded to the buyer. | ||||
| @ -1040,8 +968,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        DOLLARDE(fractional_dollar,fraction) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $fractional_dollar Fractional Dollar | ||||
|      * @param int $fraction Fraction | ||||
|      * | ||||
| @ -1063,7 +989,7 @@ class Financial | ||||
|         $dollars = floor($fractional_dollar); | ||||
|         $cents = fmod($fractional_dollar, 1); | ||||
|         $cents /= $fraction; | ||||
|         $cents *= pow(10, ceil(log10($fraction))); | ||||
|         $cents *= 10 ** ceil(log10($fraction)); | ||||
| 
 | ||||
|         return $dollars + $cents; | ||||
|     } | ||||
| @ -1078,8 +1004,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        DOLLARFR(decimal_dollar,fraction) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $decimal_dollar Decimal Dollar | ||||
|      * @param int $fraction Fraction | ||||
|      * | ||||
| @ -1101,7 +1025,7 @@ class Financial | ||||
|         $dollars = floor($decimal_dollar); | ||||
|         $cents = fmod($decimal_dollar, 1); | ||||
|         $cents *= $fraction; | ||||
|         $cents *= pow(10, -ceil(log10($fraction))); | ||||
|         $cents *= 10 ** (-ceil(log10($fraction))); | ||||
| 
 | ||||
|         return $dollars + $cents; | ||||
|     } | ||||
| @ -1115,8 +1039,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        EFFECT(nominal_rate,npery) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $nominal_rate Nominal interest rate | ||||
|      * @param int $npery Number of compounding payments per year | ||||
|      * | ||||
| @ -1132,7 +1054,7 @@ class Financial | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         return pow((1 + $nominal_rate / $npery), $npery) - 1; | ||||
|         return (1 + $nominal_rate / $npery) ** $npery - 1; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1143,8 +1065,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        FV(rate,nper,pmt[,pv[,type]]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $rate The interest rate per period | ||||
|      * @param int $nper Total number of payment periods in an annuity | ||||
|      * @param float $pmt The payment made each period: it cannot change over the | ||||
| @ -1173,7 +1093,7 @@ class Financial | ||||
| 
 | ||||
|         // Calculate
 | ||||
|         if ($rate !== null && $rate != 0) { | ||||
|             return -$pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate * $type) * (pow(1 + $rate, $nper) - 1) / $rate; | ||||
|             return -$pv * (1 + $rate) ** $nper - $pmt * (1 + $rate * $type) * ((1 + $rate) ** $nper - 1) / $rate; | ||||
|         } | ||||
| 
 | ||||
|         return -$pv - $pmt * $nper; | ||||
| @ -1442,9 +1362,9 @@ class Financial | ||||
|         $npv_pos = $npv_neg = 0.0; | ||||
|         foreach ($values as $i => $v) { | ||||
|             if ($v >= 0) { | ||||
|                 $npv_pos += $v / pow($rr, $i); | ||||
|                 $npv_pos += $v / $rr ** $i; | ||||
|             } else { | ||||
|                 $npv_neg += $v / pow($fr, $i); | ||||
|                 $npv_neg += $v / $fr ** $i; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1452,8 +1372,8 @@ class Financial | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
| 
 | ||||
|         $mirr = pow((-$npv_pos * pow($rr, $n)) | ||||
|                 / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0; | ||||
|         $mirr = ((-$npv_pos * $rr ** $n) | ||||
|                 / ($npv_neg * ($rr))) ** (1.0 / ($n - 1)) - 1.0; | ||||
| 
 | ||||
|         return is_finite($mirr) ? $mirr : Functions::VALUE(); | ||||
|     } | ||||
| @ -1479,7 +1399,7 @@ class Financial | ||||
|         } | ||||
| 
 | ||||
|         // Calculate
 | ||||
|         return $npery * (pow($effect_rate + 1, 1 / $npery) - 1); | ||||
|         return $npery * (($effect_rate + 1) ** (1 / $npery) - 1); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1544,7 +1464,7 @@ class Financial | ||||
|         for ($i = 1; $i <= $countArgs; ++$i) { | ||||
|             // Is it a numeric value?
 | ||||
|             if (is_numeric($aArgs[$i - 1])) { | ||||
|                 $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i); | ||||
|                 $returnValue += $aArgs[$i - 1] / (1 + $rate) ** $i; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1607,7 +1527,7 @@ class Financial | ||||
| 
 | ||||
|         // Calculate
 | ||||
|         if ($rate !== null && $rate != 0) { | ||||
|             return (-$fv - $pv * pow(1 + $rate, $nper)) / (1 + $rate * $type) / ((pow(1 + $rate, $nper) - 1) / $rate); | ||||
|             return (-$fv - $pv * (1 + $rate) ** $nper) / (1 + $rate * $type) / (((1 + $rate) ** $nper - 1) / $rate); | ||||
|         } | ||||
| 
 | ||||
|         return (-$pv - $fv) / $nper; | ||||
| @ -1650,22 +1570,54 @@ class Financial | ||||
|         return $interestAndPrincipal[1]; | ||||
|     } | ||||
| 
 | ||||
|     private static function validatePrice($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis) | ||||
|     { | ||||
|         if (is_string($settlement)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (is_string($maturity)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (!is_numeric($rate)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (!is_numeric($yield)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (!is_numeric($redemption)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (!is_numeric($frequency)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (!is_numeric($basis)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
| 
 | ||||
|         return ''; | ||||
|     } | ||||
| 
 | ||||
|     public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis = 0) | ||||
|     { | ||||
|         $settlement = Functions::flattenSingleValue($settlement); | ||||
|         $maturity = Functions::flattenSingleValue($maturity); | ||||
|         $rate = (float) Functions::flattenSingleValue($rate); | ||||
|         $yield = (float) Functions::flattenSingleValue($yield); | ||||
|         $redemption = (float) Functions::flattenSingleValue($redemption); | ||||
|         $frequency = (int) Functions::flattenSingleValue($frequency); | ||||
|         $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis); | ||||
|         $rate = Functions::flattenSingleValue($rate); | ||||
|         $yield = Functions::flattenSingleValue($yield); | ||||
|         $redemption = Functions::flattenSingleValue($redemption); | ||||
|         $frequency = Functions::flattenSingleValue($frequency); | ||||
|         $basis = Functions::flattenSingleValue($basis); | ||||
| 
 | ||||
|         if (is_string($settlement = DateTime::getDateValue($settlement))) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if (is_string($maturity = DateTime::getDateValue($maturity))) { | ||||
|             return Functions::VALUE(); | ||||
|         $settlement = DateTime::getDateValue($settlement); | ||||
|         $maturity = DateTime::getDateValue($maturity); | ||||
|         $rslt = self::validatePrice($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis); | ||||
|         if ($rslt) { | ||||
|             return $rslt; | ||||
|         } | ||||
|         $rate = (float) $rate; | ||||
|         $yield = (float) $yield; | ||||
|         $redemption = (float) $redemption; | ||||
|         $frequency = (int) $frequency; | ||||
|         $basis = (int) $basis; | ||||
| 
 | ||||
|         if (($settlement > $maturity) || | ||||
|             (!self::isValidFrequency($frequency)) || | ||||
| @ -1682,9 +1634,9 @@ class Financial | ||||
|         $rfp = 100 * ($rate / $frequency); | ||||
|         $de = $dsc / $e; | ||||
| 
 | ||||
|         $result = $redemption / pow($baseYF, (--$n + $de)); | ||||
|         $result = $redemption / $baseYF ** (--$n + $de); | ||||
|         for ($k = 0; $k <= $n; ++$k) { | ||||
|             $result += $rfp / (pow($baseYF, ($k + $de))); | ||||
|             $result += $rfp / ($baseYF ** ($k + $de)); | ||||
|         } | ||||
|         $result -= $rfp * ($a / $e); | ||||
| 
 | ||||
| @ -1830,7 +1782,7 @@ class Financial | ||||
| 
 | ||||
|         // Calculate
 | ||||
|         if ($rate !== null && $rate != 0) { | ||||
|             return (-$pmt * (1 + $rate * $type) * ((pow(1 + $rate, $nper) - 1) / $rate) - $fv) / pow(1 + $rate, $nper); | ||||
|             return (-$pmt * (1 + $rate * $type) * (((1 + $rate) ** $nper - 1) / $rate) - $fv) / (1 + $rate) ** $nper; | ||||
|         } | ||||
| 
 | ||||
|         return -$fv - $pmt * $nper; | ||||
| @ -1847,8 +1799,6 @@ class Financial | ||||
|      * Excel Function: | ||||
|      *        RATE(nper,pmt,pv[,fv[,type[,guess]]]) | ||||
|      * | ||||
|      * @category Financial Functions | ||||
|      * | ||||
|      * @param float $nper The total number of payment periods in an annuity | ||||
|      * @param float $pmt The payment made each period and cannot change over the life | ||||
|      *                                    of the annuity. | ||||
| @ -1865,7 +1815,7 @@ class Financial | ||||
|      * @param float $guess Your guess for what the rate will be. | ||||
|      *                                    If you omit guess, it is assumed to be 10 percent. | ||||
|      * | ||||
|      * @return float | ||||
|      * @return float|string | ||||
|      */ | ||||
|     public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) | ||||
|     { | ||||
| @ -1877,38 +1827,39 @@ class Financial | ||||
|         $guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess); | ||||
| 
 | ||||
|         $rate = $guess; | ||||
|         if (abs($rate) < self::FINANCIAL_PRECISION) { | ||||
|             $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; | ||||
|         } else { | ||||
|             $f = exp($nper * log(1 + $rate)); | ||||
|             $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; | ||||
|         } | ||||
|         $y0 = $pv + $pmt * $nper + $fv; | ||||
|         $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; | ||||
| 
 | ||||
|         // find root by secant method
 | ||||
|         $i = $x0 = 0.0; | ||||
|         $x1 = $rate; | ||||
|         while ((abs($y0 - $y1) > self::FINANCIAL_PRECISION) && ($i < self::FINANCIAL_MAX_ITERATIONS)) { | ||||
|             $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); | ||||
|             $x0 = $x1; | ||||
|             $x1 = $rate; | ||||
|             if (($nper * abs($pmt)) > ($pv - $fv)) { | ||||
|                 $x1 = abs($x1); | ||||
|         // rest of code adapted from python/numpy
 | ||||
|         $close = false; | ||||
|         $iter = 0; | ||||
|         while (!$close && $iter < self::FINANCIAL_MAX_ITERATIONS) { | ||||
|             $nextdiff = self::rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type); | ||||
|             if (!is_numeric($nextdiff)) { | ||||
|                 break; | ||||
|             } | ||||
|             if (abs($rate) < self::FINANCIAL_PRECISION) { | ||||
|                 $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; | ||||
|             } else { | ||||
|                 $f = exp($nper * log(1 + $rate)); | ||||
|                 $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; | ||||
|             } | ||||
| 
 | ||||
|             $y0 = $y1; | ||||
|             $y1 = $y; | ||||
|             ++$i; | ||||
|             $rate1 = $rate - $nextdiff; | ||||
|             $close = abs($rate1 - $rate) < self::FINANCIAL_PRECISION; | ||||
|             ++$iter; | ||||
|             $rate = $rate1; | ||||
|         } | ||||
| 
 | ||||
|         return $rate; | ||||
|         return $close ? $rate : Functions::NAN(); | ||||
|     } | ||||
| 
 | ||||
|     private static function rateNextGuess($rate, $nper, $pmt, $pv, $fv, $type) | ||||
|     { | ||||
|         if ($rate == 0) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
|         $tt1 = ($rate + 1) ** $nper; | ||||
|         $tt2 = ($rate + 1) ** ($nper - 1); | ||||
|         $numerator = $fv + $tt1 * $pv + $pmt * ($tt1 - 1) * ($rate * $type + 1) / $rate; | ||||
|         $denominator = $nper * $tt2 * $pv - $pmt * ($tt1 - 1) * ($rate * $type + 1) / ($rate * $rate) | ||||
|              + $nper * $pmt * $tt2 * ($rate * $type + 1) / $rate | ||||
|              + $pmt * ($tt1 - 1) * $type / $rate; | ||||
|         if ($denominator == 0) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         return $numerator / $denominator; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -1980,7 +1931,7 @@ class Financial | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         return pow($fv / $pv, 1 / $nper) - 1; | ||||
|         return ($fv / $pv) ** (1 / $nper) - 1; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -2183,6 +2134,84 @@ class Financial | ||||
|         return Functions::VALUE(); | ||||
|     } | ||||
| 
 | ||||
|     private static function bothNegAndPos($neg, $pos) | ||||
|     { | ||||
|         return $neg && $pos; | ||||
|     } | ||||
| 
 | ||||
|     private static function xirrPart2(&$values) | ||||
|     { | ||||
|         $valCount = count($values); | ||||
|         $foundpos = false; | ||||
|         $foundneg = false; | ||||
|         for ($i = 0; $i < $valCount; ++$i) { | ||||
|             $fld = $values[$i]; | ||||
|             if (!is_numeric($fld)) { | ||||
|                 return Functions::VALUE(); | ||||
|             } elseif ($fld > 0) { | ||||
|                 $foundpos = true; | ||||
|             } elseif ($fld < 0) { | ||||
|                 $foundneg = true; | ||||
|             } | ||||
|         } | ||||
|         if (!self::bothNegAndPos($foundneg, $foundpos)) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         return ''; | ||||
|     } | ||||
| 
 | ||||
|     private static function xirrPart1(&$values, &$dates) | ||||
|     { | ||||
|         if ((!is_array($values)) && (!is_array($dates))) { | ||||
|             return Functions::NA(); | ||||
|         } | ||||
|         $values = Functions::flattenArray($values); | ||||
|         $dates = Functions::flattenArray($dates); | ||||
|         if (count($values) != count($dates)) { | ||||
|             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(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return self::xirrPart2($values); | ||||
|     } | ||||
| 
 | ||||
|     private static function xirrPart3($values, $dates, $x1, $x2) | ||||
|     { | ||||
|         $f = self::xnpvOrdered($x1, $values, $dates, false); | ||||
|         if ($f < 0.0) { | ||||
|             $rtb = $x1; | ||||
|             $dx = $x2 - $x1; | ||||
|         } else { | ||||
|             $rtb = $x2; | ||||
|             $dx = $x1 - $x2; | ||||
|         } | ||||
| 
 | ||||
|         $rslt = Functions::VALUE(); | ||||
|         for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { | ||||
|             $dx *= 0.5; | ||||
|             $x_mid = $rtb + $dx; | ||||
|             $f_mid = self::xnpvOrdered($x_mid, $values, $dates, false); | ||||
|             if ($f_mid <= 0.0) { | ||||
|                 $rtb = $x_mid; | ||||
|             } | ||||
|             if ((abs($f_mid) < self::FINANCIAL_PRECISION) || (abs($dx) < self::FINANCIAL_PRECISION)) { | ||||
|                 $rslt = $x_mid; | ||||
| 
 | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return $rslt; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * XIRR. | ||||
|      * | ||||
| @ -2202,73 +2231,37 @@ class Financial | ||||
|      */ | ||||
|     public static function XIRR($values, $dates, $guess = 0.1) | ||||
|     { | ||||
|         if ((!is_array($values)) && (!is_array($dates))) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         $values = Functions::flattenArray($values); | ||||
|         $dates = Functions::flattenArray($dates); | ||||
|         $guess = Functions::flattenSingleValue($guess); | ||||
|         if (count($values) != count($dates)) { | ||||
|             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(); | ||||
|         $rslt = self::xirrPart1($values, $dates); | ||||
|         if ($rslt) { | ||||
|             return $rslt; | ||||
|         } | ||||
| 
 | ||||
|         // create an initial range, with a root somewhere between 0 and guess
 | ||||
|         $guess = Functions::flattenSingleValue($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; | ||||
|         } | ||||
|         $x2 = $guess ? $guess : 0.1; | ||||
|         $f1 = self::xnpvOrdered($x1, $values, $dates, false); | ||||
|         $f2 = self::xnpvOrdered($x2, $values, $dates, false); | ||||
|         $found = false; | ||||
|         for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { | ||||
|             if (!is_numeric($f1) || !is_numeric($f2)) { | ||||
|                 break; | ||||
|             } | ||||
|             if (($f1 * $f2) < 0.0) { | ||||
|                 $found = true; | ||||
| 
 | ||||
|                 break; | ||||
|             } elseif (abs($f1) < abs($f2)) { | ||||
|                 $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates); | ||||
|                 $f1 = self::xnpvOrdered($x1 += 1.6 * ($x1 - $x2), $values, $dates, false); | ||||
|             } else { | ||||
|                 $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates); | ||||
|                 $f2 = self::xnpvOrdered($x2 += 1.6 * ($x2 - $x1), $values, $dates, false); | ||||
|             } | ||||
|         } | ||||
|         if (($f1 * $f2) > 0.0) { | ||||
|         if (!$found) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
| 
 | ||||
|         $f = self::XNPV($x1, $values, $dates); | ||||
|         if ($f < 0.0) { | ||||
|             $rtb = $x1; | ||||
|             $dx = $x2 - $x1; | ||||
|         } else { | ||||
|             $rtb = $x2; | ||||
|             $dx = $x1 - $x2; | ||||
|         } | ||||
| 
 | ||||
|         for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) { | ||||
|             $dx *= 0.5; | ||||
|             $x_mid = $rtb + $dx; | ||||
|             $f_mid = self::XNPV($x_mid, $values, $dates); | ||||
|             if ($f_mid <= 0.0) { | ||||
|                 $rtb = $x_mid; | ||||
|             } | ||||
|             if ((abs($f_mid) < self::FINANCIAL_PRECISION) || (abs($dx) < self::FINANCIAL_PRECISION)) { | ||||
|                 return $x_mid; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return Functions::VALUE(); | ||||
|         return self::xirrPart3($values, $dates, $x1, $x2); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -2293,32 +2286,61 @@ class Financial | ||||
|      */ | ||||
|     public static function XNPV($rate, $values, $dates) | ||||
|     { | ||||
|         $rate = Functions::flattenSingleValue($rate); | ||||
|         return self::xnpvOrdered($rate, $values, $dates, true); | ||||
|     } | ||||
| 
 | ||||
|     private static function validateXnpv($rate, $values, $dates) | ||||
|     { | ||||
|         if (!is_numeric($rate)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         if ((!is_array($values)) || (!is_array($dates))) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
|         $values = Functions::flattenArray($values); | ||||
|         $dates = Functions::flattenArray($dates); | ||||
|         $valCount = count($values); | ||||
|         if ($valCount != count($dates)) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
|         if ((min($values) > 0) || (max($values) < 0)) { | ||||
|         if ($valCount > 1 && ((min($values) > 0) || (max($values) < 0))) { | ||||
|             return Functions::NAN(); | ||||
|         } | ||||
|         $date0 = DateTime::getDateValue($dates[0]); | ||||
|         if (is_string($date0)) { | ||||
|             return Functions::VALUE(); | ||||
|         } | ||||
| 
 | ||||
|         return ''; | ||||
|     } | ||||
| 
 | ||||
|     private static function xnpvOrdered($rate, $values, $dates, $ordered = true) | ||||
|     { | ||||
|         $rate = Functions::flattenSingleValue($rate); | ||||
|         $values = Functions::flattenArray($values); | ||||
|         $dates = Functions::flattenArray($dates); | ||||
|         $valCount = count($values); | ||||
|         $date0 = DateTime::getDateValue($dates[0]); | ||||
|         $rslt = self::validateXnpv($rate, $values, $dates); | ||||
|         if ($rslt) { | ||||
|             return $rslt; | ||||
|         } | ||||
|         $xnpv = 0.0; | ||||
|         for ($i = 0; $i < $valCount; ++$i) { | ||||
|             if (!is_numeric($values[$i])) { | ||||
|                 return Functions::VALUE(); | ||||
|             } | ||||
|             $xnpv += $values[$i] / pow(1 + $rate, DateTime::DATEDIF($dates[0], $dates[$i], 'd') / 365); | ||||
|             $datei = DateTime::getDateValue($dates[$i]); | ||||
|             if (is_string($datei)) { | ||||
|                 return Functions::VALUE(); | ||||
|             } | ||||
|             if ($date0 > $datei) { | ||||
|                 $dif = $ordered ? Functions::NAN() : -DateTime::DATEDIF($datei, $date0, 'd'); | ||||
|             } else { | ||||
|                 $dif = DateTime::DATEDIF($date0, $datei, 'd'); | ||||
|             } | ||||
|             if (!is_numeric($dif)) { | ||||
|                 return $dif; | ||||
|             } | ||||
|             $xnpv += $values[$i] / (1 + $rate) ** ($dif / 365); | ||||
|         } | ||||
| 
 | ||||
|         return (is_finite($xnpv)) ? $xnpv : Functions::VALUE(); | ||||
|         return is_finite($xnpv) ? $xnpv : Functions::VALUE(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -62,8 +62,6 @@ class FormulaParser | ||||
|      * Create a new FormulaParser. | ||||
|      * | ||||
|      * @param string $pFormula Formula to parse | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function __construct($pFormula = '') | ||||
|     { | ||||
| @ -93,8 +91,6 @@ class FormulaParser | ||||
|      * | ||||
|      * @param int $pId Token id | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getToken($pId = 0) | ||||
| @ -129,7 +125,7 @@ class FormulaParser | ||||
|     /** | ||||
|      * Parse to tokens. | ||||
|      */ | ||||
|     private function parseToTokens() | ||||
|     private function parseToTokens(): void | ||||
|     { | ||||
|         // No attempt is made to verify formulas; assumes formulas are derived from Excel, where
 | ||||
|         // they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions.
 | ||||
|  | ||||
| @ -103,7 +103,7 @@ class FormulaToken | ||||
|      * | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setValue($value) | ||||
|     public function setValue($value): void | ||||
|     { | ||||
|         $this->value = $value; | ||||
|     } | ||||
| @ -123,7 +123,7 @@ class FormulaToken | ||||
|      * | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setTokenType($value) | ||||
|     public function setTokenType($value): void | ||||
|     { | ||||
|         $this->tokenType = $value; | ||||
|     } | ||||
| @ -143,7 +143,7 @@ class FormulaToken | ||||
|      * | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setTokenSubType($value) | ||||
|     public function setTokenSubType($value): void | ||||
|     { | ||||
|         $this->tokenSubType = $value; | ||||
|     } | ||||
|  | ||||
| @ -57,8 +57,6 @@ class Functions | ||||
|     /** | ||||
|      * Set the Compatibility Mode. | ||||
|      * | ||||
|      * @category Function Configuration | ||||
|      * | ||||
|      * @param string $compatibilityMode Compatibility Mode | ||||
|      *                                                Permitted values are: | ||||
|      *                                                    Functions::COMPATIBILITY_EXCEL            'Excel' | ||||
| @ -84,8 +82,6 @@ class Functions | ||||
|     /** | ||||
|      * Return the current Compatibility Mode. | ||||
|      * | ||||
|      * @category Function Configuration | ||||
|      * | ||||
|      * @return string Compatibility Mode | ||||
|      *                            Possible Return values are: | ||||
|      *                                Functions::COMPATIBILITY_EXCEL            'Excel' | ||||
| @ -100,8 +96,6 @@ class Functions | ||||
|     /** | ||||
|      * Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object). | ||||
|      * | ||||
|      * @category Function Configuration | ||||
|      * | ||||
|      * @param string $returnDateType Return Date Format | ||||
|      *                                                Permitted values are: | ||||
|      *                                                    Functions::RETURNDATE_UNIX_TIMESTAMP        'P' | ||||
| @ -127,8 +121,6 @@ class Functions | ||||
|     /** | ||||
|      * Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object). | ||||
|      * | ||||
|      * @category Function Configuration | ||||
|      * | ||||
|      * @return string Return Date Format | ||||
|      *                            Possible Return values are: | ||||
|      *                                Functions::RETURNDATE_UNIX_TIMESTAMP        'P' | ||||
| @ -143,8 +135,6 @@ class Functions | ||||
|     /** | ||||
|      * DUMMY. | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #Not Yet Implemented
 | ||||
|      */ | ||||
|     public static function DUMMY() | ||||
| @ -155,8 +145,6 @@ class Functions | ||||
|     /** | ||||
|      * DIV0. | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #Not Yet Implemented
 | ||||
|      */ | ||||
|     public static function DIV0() | ||||
| @ -173,8 +161,6 @@ class Functions | ||||
|      * Returns the error value #N/A
 | ||||
|      *        #N/A is the error value that means "no value is available."
 | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @return string #N/A!
 | ||||
|      */ | ||||
|     public static function NA() | ||||
| @ -187,8 +173,6 @@ class Functions | ||||
|      * | ||||
|      * Returns the error value #NUM!
 | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #NUM!
 | ||||
|      */ | ||||
|     public static function NAN() | ||||
| @ -201,8 +185,6 @@ class Functions | ||||
|      * | ||||
|      * Returns the error value #NAME?
 | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #NAME?
 | ||||
|      */ | ||||
|     public static function NAME() | ||||
| @ -215,8 +197,6 @@ class Functions | ||||
|      * | ||||
|      * Returns the error value #REF!
 | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #REF!
 | ||||
|      */ | ||||
|     public static function REF() | ||||
| @ -229,8 +209,6 @@ class Functions | ||||
|      * | ||||
|      * Returns the error value #NULL!
 | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #NULL!
 | ||||
|      */ | ||||
|     public static function null() | ||||
| @ -243,8 +221,6 @@ class Functions | ||||
|      * | ||||
|      * Returns the error value #VALUE!
 | ||||
|      * | ||||
|      * @category Error Returns | ||||
|      * | ||||
|      * @return string #VALUE!
 | ||||
|      */ | ||||
|     public static function VALUE() | ||||
| @ -660,7 +636,7 @@ class Functions | ||||
|      * | ||||
|      * @return bool|string | ||||
|      */ | ||||
|     public static function isFormula($cellReference = '', Cell $pCell = null) | ||||
|     public static function isFormula($cellReference = '', ?Cell $pCell = null) | ||||
|     { | ||||
|         if ($pCell === null) { | ||||
|             return self::REF(); | ||||
|  | ||||
| @ -12,8 +12,6 @@ class Logical | ||||
|      * Excel Function: | ||||
|      *        =TRUE() | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @return bool True | ||||
|      */ | ||||
|     public static function true() | ||||
| @ -29,8 +27,6 @@ class Logical | ||||
|      * Excel Function: | ||||
|      *        =FALSE() | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @return bool False | ||||
|      */ | ||||
|     public static function false() | ||||
| @ -80,8 +76,6 @@ class Logical | ||||
|      *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
 | ||||
|      *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return bool|string the logical AND of the arguments | ||||
| @ -123,8 +117,6 @@ class Logical | ||||
|      *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
 | ||||
|      *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * | ||||
|      * @return bool|string the logical OR of the arguments | ||||
| @ -166,8 +158,6 @@ class Logical | ||||
|      *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
 | ||||
|      *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * | ||||
|      * @return bool|string the logical XOR of the arguments | ||||
| @ -207,8 +197,6 @@ class Logical | ||||
|      *        If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds
 | ||||
|      *            the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE | ||||
|      * | ||||
|      * @return bool|string the boolean inverse of the argument | ||||
| @ -256,8 +244,6 @@ class Logical | ||||
|      *            If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. | ||||
|      *            ReturnIfFalse can be another formula. | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $condition Condition to evaluate | ||||
|      * @param mixed $returnIfTrue Value to return when condition is true | ||||
|      * @param mixed $returnIfFalse Optional value to return when condition is false | ||||
| @ -294,8 +280,6 @@ class Logical | ||||
|      *         default | ||||
|      *              Optional. It is the default to return if expression does not match any of the values (value1, value2, ... value_n). | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $arguments Statement arguments | ||||
|      * | ||||
|      * @return mixed The value of matched expression | ||||
| @ -337,8 +321,6 @@ class Logical | ||||
|      * Excel Function: | ||||
|      *        =IFERROR(testValue,errorpart) | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param mixed $testValue Value to check, is also the value returned when no error | ||||
|      * @param mixed $errorpart Value to return when testValue is an error condition | ||||
|      * | ||||
| @ -358,8 +340,6 @@ class Logical | ||||
|      * 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 | ||||
|      * | ||||
|  | ||||
| @ -230,15 +230,13 @@ class LookupRef | ||||
|      * Excel Function: | ||||
|      *        =HYPERLINK(linkURL,displayName) | ||||
|      * | ||||
|      * @category Logical Functions | ||||
|      * | ||||
|      * @param string $linkURL Value to check, is also the value returned when no error | ||||
|      * @param string $displayName Value to return when testValue is an error condition | ||||
|      * @param Cell $pCell The cell to set the hyperlink in | ||||
|      * | ||||
|      * @return mixed The value of $displayName (or $linkURL if $displayName was blank) | ||||
|      */ | ||||
|     public static function HYPERLINK($linkURL = '', $displayName = null, Cell $pCell = null) | ||||
|     public static function HYPERLINK($linkURL = '', $displayName = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         $linkURL = ($linkURL === null) ? '' : Functions::flattenSingleValue($linkURL); | ||||
|         $displayName = ($displayName === null) ? '' : Functions::flattenSingleValue($displayName); | ||||
| @ -273,9 +271,9 @@ class LookupRef | ||||
|      * | ||||
|      * @return mixed The cells referenced by cellAddress | ||||
|      * | ||||
|      * @todo    Support for the optional a1 parameter introduced in Excel 2010 | ||||
|      * @TODO    Support for the optional a1 parameter introduced in Excel 2010 | ||||
|      */ | ||||
|     public static function INDIRECT($cellAddress = null, Cell $pCell = null) | ||||
|     public static function INDIRECT($cellAddress = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         $cellAddress = Functions::flattenSingleValue($cellAddress); | ||||
|         if ($cellAddress === null || $cellAddress === '') { | ||||
| @ -339,11 +337,10 @@ class LookupRef | ||||
|      *                                starting reference). | ||||
|      * @param mixed $height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. | ||||
|      * @param mixed $width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. | ||||
|      * @param null|Cell $pCell | ||||
|      * | ||||
|      * @return string A reference to a cell or range of cells | ||||
|      */ | ||||
|     public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $height = null, $width = null, Cell $pCell = null) | ||||
|     public static function OFFSET($cellAddress = null, $rows = 0, $columns = 0, $height = null, $width = null, ?Cell $pCell = null) | ||||
|     { | ||||
|         $rows = Functions::flattenSingleValue($rows); | ||||
|         $columns = Functions::flattenSingleValue($columns); | ||||
| @ -419,14 +416,6 @@ class LookupRef | ||||
|      * Excel Function: | ||||
|      *        =CHOOSE(index_num, value1, [value2], ...) | ||||
|      * | ||||
|      * @param mixed $index_num Specifies which value argument is selected. | ||||
|      *                            Index_num must be a number between 1 and 254, or a formula or reference to a cell containing a number | ||||
|      *                                between 1 and 254. | ||||
|      * @param mixed $value1 ... Value1 is required, subsequent values are optional. | ||||
|      *                            Between 1 to 254 value arguments from which CHOOSE selects a value or an action to perform based on | ||||
|      *                                index_num. The arguments can be numbers, cell references, defined names, formulas, functions, or | ||||
|      *                                text. | ||||
|      * | ||||
|      * @return mixed The selected value | ||||
|      */ | ||||
|     public static function CHOOSE(...$chooseArgs) | ||||
| @ -945,7 +934,7 @@ class LookupRef | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function FORMULATEXT($cellReference = '', Cell $pCell = null) | ||||
|     public static function FORMULATEXT($cellReference = '', ?Cell $pCell = null) | ||||
|     { | ||||
|         if ($pCell === null) { | ||||
|             return Functions::REF(); | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Calculation; | ||||
| 
 | ||||
| use Exception; | ||||
| use Matrix\Exception as MatrixException; | ||||
| use Matrix\Matrix; | ||||
| 
 | ||||
| @ -46,8 +47,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        ARABIC(text) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param string $roman | ||||
|      * | ||||
|      * @return int|string the arabic numberal contrived from the roman numeral | ||||
| @ -68,7 +67,7 @@ class MathTrig | ||||
| 
 | ||||
|         try { | ||||
|             $arabic = self::calculateArabic(str_split($roman)); | ||||
|         } catch (\Exception $e) { | ||||
|         } catch (Exception $e) { | ||||
|             return Functions::VALUE(); // Invalid character detected
 | ||||
|         } | ||||
| 
 | ||||
| @ -82,7 +81,6 @@ class MathTrig | ||||
|     /** | ||||
|      * Recursively calculate the arabic value of a roman numeral. | ||||
|      * | ||||
|      * @param array $roman | ||||
|      * @param int $sum | ||||
|      * @param int $subtract | ||||
|      * | ||||
| @ -102,7 +100,7 @@ class MathTrig | ||||
| 
 | ||||
|         $numeral = array_shift($roman); | ||||
|         if (!isset($lookup[$numeral])) { | ||||
|             throw new \Exception('Invalid character detected'); | ||||
|             throw new Exception('Invalid character detected'); | ||||
|         } | ||||
| 
 | ||||
|         $arabic = $lookup[$numeral]; | ||||
| @ -136,8 +134,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        ATAN2(xCoordinate,yCoordinate) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $xCoordinate the x-coordinate of the point | ||||
|      * @param float $yCoordinate the y-coordinate of the point | ||||
|      * | ||||
| @ -174,8 +170,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        BASE(Number, Radix [Min_length]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number | ||||
|      * @param float $radix | ||||
|      * @param int $minLength | ||||
| @ -220,8 +214,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        CEILING(number[,significance]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number the number you want to round | ||||
|      * @param float $significance the multiple to which you want to round | ||||
|      * | ||||
| @ -259,8 +251,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        COMBIN(numObjs,numInSet) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param int $numObjs Number of different objects | ||||
|      * @param int $numInSet Number of objects in each combination | ||||
|      * | ||||
| @ -296,8 +286,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        EVEN(number) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number Number to round | ||||
|      * | ||||
|      * @return int|string Rounded Number, or a string containing an error | ||||
| @ -330,8 +318,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        FACT(factVal) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $factVal Factorial Value | ||||
|      * | ||||
|      * @return int|string Factorial, or a string containing an error | ||||
| @ -369,8 +355,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        FACTDOUBLE(factVal) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $factVal Factorial Value | ||||
|      * | ||||
|      * @return int|string Double Factorial, or a string containing an error | ||||
| @ -404,8 +388,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        FLOOR(number[,significance]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number Number to round | ||||
|      * @param float $significance Significance | ||||
|      * | ||||
| @ -446,8 +428,6 @@ class MathTrig | ||||
|      * 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 | ||||
| @ -487,8 +467,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        FLOOR.PRECISE(number[,significance]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number Number to round | ||||
|      * @param float $significance Significance | ||||
|      * | ||||
| @ -527,8 +505,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        GCD(number1[,number2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return int|mixed|string Greatest Common Divisor, or a string containing an error | ||||
| @ -561,8 +537,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        INT(number) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param float $number Number to cast to an integer | ||||
|      * | ||||
|      * @return int|string Integer value, or a string containing an error | ||||
| @ -594,8 +568,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        LCM(number1[,number2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return int|string Lowest Common Multiplier, or a string containing an error | ||||
| @ -618,7 +590,7 @@ class MathTrig | ||||
|             $myCountedFactors = array_count_values($myFactors); | ||||
|             $myPoweredFactors = []; | ||||
|             foreach ($myCountedFactors as $myCountedFactor => $myCountedPower) { | ||||
|                 $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor, $myCountedPower); | ||||
|                 $myPoweredFactors[$myCountedFactor] = $myCountedFactor ** $myCountedPower; | ||||
|             } | ||||
|             foreach ($myPoweredFactors as $myPoweredValue => $myPoweredFactor) { | ||||
|                 if (isset($allPoweredFactors[$myPoweredValue])) { | ||||
| @ -645,8 +617,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        LOG(number[,base]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @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. | ||||
|      * | ||||
| @ -675,8 +645,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        MDETERM(array) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param array $matrixValues A matrix of values | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -727,8 +695,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        MINVERSE(array) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param array $matrixValues A matrix of values | ||||
|      * | ||||
|      * @return array|string The result, or a string containing an error | ||||
| @ -986,7 +952,7 @@ class MathTrig | ||||
|         } | ||||
| 
 | ||||
|         // Return
 | ||||
|         $result = pow($x, $y); | ||||
|         $result = $x ** $y; | ||||
| 
 | ||||
|         return (!is_nan($result) && !is_infinite($result)) ? $result : Functions::NAN(); | ||||
|     } | ||||
| @ -999,8 +965,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        PRODUCT(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -1039,8 +1003,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        QUOTIENT(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -1139,10 +1101,10 @@ class MathTrig | ||||
| 
 | ||||
|         if ((is_numeric($number)) && (is_numeric($digits))) { | ||||
|             if ($number < 0.0) { | ||||
|                 return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN); | ||||
|                 return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN); | ||||
|             } | ||||
| 
 | ||||
|             return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN); | ||||
|             return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_DOWN); | ||||
|         } | ||||
| 
 | ||||
|         return Functions::VALUE(); | ||||
| @ -1165,10 +1127,10 @@ class MathTrig | ||||
| 
 | ||||
|         if ((is_numeric($number)) && (is_numeric($digits))) { | ||||
|             if ($number < 0.0) { | ||||
|                 return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP); | ||||
|                 return round($number + 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP); | ||||
|             } | ||||
| 
 | ||||
|             return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP); | ||||
|             return round($number - 0.5 * 0.1 ** $digits, $digits, PHP_ROUND_HALF_UP); | ||||
|         } | ||||
| 
 | ||||
|         return Functions::VALUE(); | ||||
| @ -1179,9 +1141,6 @@ class MathTrig | ||||
|      * | ||||
|      * Returns the sum of a power series | ||||
|      * | ||||
|      * @param float $x Input value to the power series | ||||
|      * @param float $n Initial power to which you want to raise $x | ||||
|      * @param float $m Step by which to increase $n for each term in the series | ||||
|      * @param array of mixed Data Series | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -1203,7 +1162,7 @@ class MathTrig | ||||
|             foreach ($aArgs as $arg) { | ||||
|                 // Is it a numeric value?
 | ||||
|                 if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                     $returnValue += $arg * pow($x, $n + ($m * $i++)); | ||||
|                     $returnValue += $arg * $x ** ($n + ($m * $i++)); | ||||
|                 } else { | ||||
|                     return Functions::VALUE(); | ||||
|                 } | ||||
| @ -1367,8 +1326,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        SUM(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -1396,8 +1353,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        SUMIF(value1[,value2[, ...]],condition) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed $aArgs Data values | ||||
|      * @param string $condition the criteria that defines which cells will be summed | ||||
|      * @param mixed $sumArgs | ||||
| @ -1442,10 +1397,7 @@ class MathTrig | ||||
|      *    Excel Function: | ||||
|      *        SUMIFS(value1[,value2[, ...]],condition) | ||||
|      * | ||||
|      *    @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param string $condition the criteria that defines which cells will be summed | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
| @ -1500,8 +1452,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        SUMPRODUCT(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -1545,8 +1495,6 @@ class MathTrig | ||||
|      * Excel Function: | ||||
|      *        SUMSQ(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -1663,7 +1611,7 @@ class MathTrig | ||||
|         $digits = floor($digits); | ||||
| 
 | ||||
|         // Truncate
 | ||||
|         $adjust = pow(10, $digits); | ||||
|         $adjust = 10 ** $digits; | ||||
| 
 | ||||
|         if (($digits > 0) && (rtrim((int) ((abs($value) - abs((int) $value)) * $adjust), '0') < $adjust / 10)) { | ||||
|             return $value; | ||||
|  | ||||
| @ -397,10 +397,10 @@ class Statistical | ||||
|             for ($i = 1; $i <= $n; ++$i) { | ||||
|                 $divisor *= ($a + $i); | ||||
|             } | ||||
|             $summer += (pow($x, $n) / $divisor); | ||||
|             $summer += ($x ** $n / $divisor); | ||||
|         } | ||||
| 
 | ||||
|         return pow($x, $a) * exp(0 - $x) * $summer; | ||||
|         return $x ** $a * exp(0 - $x) * $summer; | ||||
|     } | ||||
| 
 | ||||
|     //
 | ||||
| @ -565,8 +565,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        AVEDEV(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -616,8 +614,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        AVERAGE(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -657,8 +653,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        AVERAGEA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -700,8 +694,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        AVERAGEIF(value1[,value2[, ...]],condition) | ||||
|      * | ||||
|      * @category Mathematical and Trigonometric Functions | ||||
|      * | ||||
|      * @param mixed $aArgs Data values | ||||
|      * @param string $condition the criteria that defines which cells will be checked | ||||
|      * @param mixed[] $averageArgs Data values | ||||
| @ -874,13 +866,13 @@ class Statistical | ||||
|                 if ($cumulative) { | ||||
|                     $summer = 0; | ||||
|                     for ($i = 0; $i <= $value; ++$i) { | ||||
|                         $summer += MathTrig::COMBIN($trials, $i) * pow($probability, $i) * pow(1 - $probability, $trials - $i); | ||||
|                         $summer += MathTrig::COMBIN($trials, $i) * $probability ** $i * (1 - $probability) ** ($trials - $i); | ||||
|                     } | ||||
| 
 | ||||
|                     return $summer; | ||||
|                 } | ||||
| 
 | ||||
|                 return MathTrig::COMBIN($trials, $value) * pow($probability, $value) * pow(1 - $probability, $trials - $value); | ||||
|                 return MathTrig::COMBIN($trials, $value) * $probability ** $value * (1 - $probability) ** ($trials - $value); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1053,8 +1045,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        COUNT(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return int | ||||
| @ -1086,8 +1076,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        COUNTA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return int | ||||
| @ -1116,8 +1104,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        COUNTBLANK(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return int | ||||
| @ -1146,8 +1132,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        COUNTIF(value1[,value2[, ...]],condition) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $aArgs Data values | ||||
|      * @param string $condition the criteria that defines which cells will be counted | ||||
|      * | ||||
| @ -1188,8 +1172,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        COUNTIFS(criteria_range1, criteria1, [criteria_range2, criteria2]…) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Criterias | ||||
|      * | ||||
|      * @return int | ||||
| @ -1295,7 +1277,7 @@ class Statistical | ||||
|      * | ||||
|      * @return int|string | ||||
|      * | ||||
|      * @todo    Warning. This implementation differs from the algorithm detailed on the MS | ||||
|      * @TODO    Warning. This implementation differs from the algorithm detailed on the MS | ||||
|      *            web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess | ||||
|      *            This eliminates a potential endless loop error, but may have an adverse affect on the | ||||
|      *            accuracy of the function (although all my tests have so far returned correct results). | ||||
| @ -1320,7 +1302,7 @@ class Statistical | ||||
|                 $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))); | ||||
|                 $t = sqrt(log(1 / (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); | ||||
|             } | ||||
| 
 | ||||
| @ -1416,8 +1398,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        DEVSQ(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -1441,9 +1421,9 @@ class Statistical | ||||
|                 } | ||||
|                 if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                     if ($returnValue === null) { | ||||
|                         $returnValue = pow(($arg - $aMean), 2); | ||||
|                         $returnValue = ($arg - $aMean) ** 2; | ||||
|                     } else { | ||||
|                         $returnValue += pow(($arg - $aMean), 2); | ||||
|                         $returnValue += ($arg - $aMean) ** 2; | ||||
|                     } | ||||
|                     ++$aCount; | ||||
|                 } | ||||
| @ -1603,7 +1583,7 @@ class Statistical | ||||
|                     return self::incompleteGamma($a, $value / $b) / self::gamma($a); | ||||
|                 } | ||||
| 
 | ||||
|                 return (1 / (pow($b, $a) * self::gamma($a))) * pow($value, $a - 1) * exp(0 - ($value / $b)); | ||||
|                 return (1 / ($b ** $a * self::gamma($a))) * $value ** ($a - 1) * exp(0 - ($value / $b)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1707,8 +1687,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        GEOMEAN(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -1721,7 +1699,7 @@ class Statistical | ||||
|         if (is_numeric($aMean) && ($aMean > 0)) { | ||||
|             $aCount = self::COUNT($aArgs); | ||||
|             if (self::MIN($aArgs) > 0) { | ||||
|                 return pow($aMean, (1 / $aCount)); | ||||
|                 return $aMean ** (1 / $aCount); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1769,8 +1747,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        HARMEAN(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -1900,7 +1876,7 @@ class Statistical | ||||
|                 } else { | ||||
|                     // Is it a numeric value?
 | ||||
|                     if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                         $summer += pow((($arg - $mean) / $stdDev), 4); | ||||
|                         $summer += (($arg - $mean) / $stdDev) ** 4; | ||||
|                         ++$count; | ||||
|                     } | ||||
|                 } | ||||
| @ -1908,7 +1884,7 @@ class Statistical | ||||
| 
 | ||||
|             // Return
 | ||||
|             if ($count > 3) { | ||||
|                 return $summer * ($count * ($count + 1) / (($count - 1) * ($count - 2) * ($count - 3))) - (3 * pow($count - 1, 2) / (($count - 2) * ($count - 3))); | ||||
|                 return $summer * ($count * ($count + 1) / (($count - 1) * ($count - 2) * ($count - 3))) - (3 * ($count - 1) ** 2 / (($count - 2) * ($count - 3))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1924,10 +1900,7 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        LARGE(value1[,value2[, ...]],entry) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param int $entry Position (ordered from the largest) in the array or range of data to return | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
|      */ | ||||
| @ -2013,9 +1986,9 @@ class Statistical | ||||
|         } | ||||
| 
 | ||||
|         return [ | ||||
|                 $bestFitLinear->getSlope(), | ||||
|                 $bestFitLinear->getIntersect(), | ||||
|             ]; | ||||
|             $bestFitLinear->getSlope(), | ||||
|             $bestFitLinear->getIntersect(), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -2078,9 +2051,9 @@ class Statistical | ||||
|         } | ||||
| 
 | ||||
|         return [ | ||||
|                 $bestFitExponential->getSlope(), | ||||
|                 $bestFitExponential->getIntersect(), | ||||
|             ]; | ||||
|             $bestFitExponential->getSlope(), | ||||
|             $bestFitExponential->getIntersect(), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -2094,7 +2067,7 @@ class Statistical | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
|      * | ||||
|      * @todo    Try implementing P J Acklam's refinement algorithm for greater | ||||
|      * @TODO    Try implementing P J Acklam's refinement algorithm for greater | ||||
|      *            accuracy if I can get my head round the mathematics | ||||
|      *            (as described at) http://home.online.no/~pjacklam/notes/invnorm/ | ||||
|      */ | ||||
| @ -2153,8 +2126,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MAX(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -2189,8 +2160,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MAXA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -2230,8 +2199,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MAXIFS(max_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data range and criterias | ||||
|      * | ||||
|      * @return float | ||||
| @ -2289,8 +2256,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MEDIAN(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -2333,8 +2298,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MIN(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -2369,8 +2332,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MINA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -2410,8 +2371,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MINIFS(min_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data range and criterias | ||||
|      * | ||||
|      * @return float | ||||
| @ -2468,11 +2427,27 @@ class Statistical | ||||
|     private static function modeCalc($data) | ||||
|     { | ||||
|         $frequencyArray = []; | ||||
|         $index = 0; | ||||
|         $maxfreq = 0; | ||||
|         $maxfreqkey = ''; | ||||
|         $maxfreqdatum = ''; | ||||
|         foreach ($data as $datum) { | ||||
|             $found = false; | ||||
|             ++$index; | ||||
|             foreach ($frequencyArray as $key => $value) { | ||||
|                 if ((string) $value['value'] == (string) $datum) { | ||||
|                     ++$frequencyArray[$key]['frequency']; | ||||
|                     $freq = $frequencyArray[$key]['frequency']; | ||||
|                     if ($freq > $maxfreq) { | ||||
|                         $maxfreq = $freq; | ||||
|                         $maxfreqkey = $key; | ||||
|                         $maxfreqdatum = $datum; | ||||
|                     } elseif ($freq == $maxfreq) { | ||||
|                         if ($frequencyArray[$key]['index'] < $frequencyArray[$maxfreqkey]['index']) { | ||||
|                             $maxfreqkey = $key; | ||||
|                             $maxfreqdatum = $datum; | ||||
|                         } | ||||
|                     } | ||||
|                     $found = true; | ||||
| 
 | ||||
|                     break; | ||||
| @ -2482,21 +2457,16 @@ class Statistical | ||||
|                 $frequencyArray[] = [ | ||||
|                     'value' => $datum, | ||||
|                     'frequency' => 1, | ||||
|                     'index' => $index, | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         foreach ($frequencyArray as $key => $value) { | ||||
|             $frequencyList[$key] = $value['frequency']; | ||||
|             $valueList[$key] = $value['value']; | ||||
|         } | ||||
|         array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray); | ||||
| 
 | ||||
|         if ($frequencyArray[0]['frequency'] == 1) { | ||||
|         if ($maxfreq <= 1) { | ||||
|             return Functions::NA(); | ||||
|         } | ||||
| 
 | ||||
|         return $frequencyArray[0]['value']; | ||||
|         return $maxfreqdatum; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -2507,8 +2477,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        MODE(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -2568,7 +2536,7 @@ class Statistical | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return (MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * (pow($probability, $successes)) * (pow(1 - $probability, $failures)); | ||||
|             return (MathTrig::COMBIN($failures + $successes - 1, $successes - 1)) * ($probability ** $successes) * ((1 - $probability) ** $failures); | ||||
|         } | ||||
| 
 | ||||
|         return Functions::VALUE(); | ||||
| @ -2603,7 +2571,7 @@ class Statistical | ||||
|                     return 0.5 * (1 + Engineering::erfVal(($value - $mean) / ($stdDev * sqrt(2)))); | ||||
|                 } | ||||
| 
 | ||||
|                 return (1 / (self::SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean, 2) / (2 * ($stdDev * $stdDev)))); | ||||
|                 return (1 / (self::SQRT2PI * $stdDev)) * exp(0 - (($value - $mean) ** 2 / (2 * ($stdDev * $stdDev)))); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -2681,10 +2649,7 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        PERCENTILE(value1[,value2[, ...]],entry) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param float $entry Percentile value in the range 0..1, inclusive. | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
|      */ | ||||
| @ -2830,13 +2795,13 @@ class Statistical | ||||
|                     $summer = 0; | ||||
|                     $floor = floor($value); | ||||
|                     for ($i = 0; $i <= $floor; ++$i) { | ||||
|                         $summer += pow($mean, $i) / MathTrig::FACT($i); | ||||
|                         $summer += $mean ** $i / MathTrig::FACT($i); | ||||
|                     } | ||||
| 
 | ||||
|                     return exp(0 - $mean) * $summer; | ||||
|                 } | ||||
| 
 | ||||
|                 return (exp(0 - $mean) * pow($mean, $value)) / MathTrig::FACT($value); | ||||
|                 return (exp(0 - $mean) * $mean ** $value) / MathTrig::FACT($value); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -2851,10 +2816,7 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        QUARTILE(value1[,value2[, ...]],entry) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param int $entry Quartile value in the range 1..3, inclusive. | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
|      */ | ||||
| @ -2968,7 +2930,7 @@ class Statistical | ||||
|             } else { | ||||
|                 // Is it a numeric value?
 | ||||
|                 if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                     $summer += pow((($arg - $mean) / $stdDev), 3); | ||||
|                     $summer += (($arg - $mean) / $stdDev) ** 3; | ||||
|                     ++$count; | ||||
|                 } | ||||
|             } | ||||
| @ -3019,10 +2981,7 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        SMALL(value1[,value2[, ...]],entry) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param int $entry Position (ordered from the smallest) in the array or range of data to return | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
|      */ | ||||
| @ -3091,8 +3050,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        STDEV(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string The result, or a string containing an error | ||||
| @ -3115,9 +3072,9 @@ class Statistical | ||||
|                 // Is it a numeric value?
 | ||||
|                 if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                     if ($returnValue === null) { | ||||
|                         $returnValue = pow(($arg - $aMean), 2); | ||||
|                         $returnValue = ($arg - $aMean) ** 2; | ||||
|                     } else { | ||||
|                         $returnValue += pow(($arg - $aMean), 2); | ||||
|                         $returnValue += ($arg - $aMean) ** 2; | ||||
|                     } | ||||
|                     ++$aCount; | ||||
|                 } | ||||
| @ -3140,8 +3097,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        STDEVA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -3167,9 +3122,9 @@ class Statistical | ||||
|                             $arg = 0; | ||||
|                         } | ||||
|                         if ($returnValue === null) { | ||||
|                             $returnValue = pow(($arg - $aMean), 2); | ||||
|                             $returnValue = ($arg - $aMean) ** 2; | ||||
|                         } else { | ||||
|                             $returnValue += pow(($arg - $aMean), 2); | ||||
|                             $returnValue += ($arg - $aMean) ** 2; | ||||
|                         } | ||||
|                         ++$aCount; | ||||
|                     } | ||||
| @ -3192,8 +3147,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        STDEVP(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -3215,9 +3168,9 @@ class Statistical | ||||
|                 // Is it a numeric value?
 | ||||
|                 if ((is_numeric($arg)) && (!is_string($arg))) { | ||||
|                     if ($returnValue === null) { | ||||
|                         $returnValue = pow(($arg - $aMean), 2); | ||||
|                         $returnValue = ($arg - $aMean) ** 2; | ||||
|                     } else { | ||||
|                         $returnValue += pow(($arg - $aMean), 2); | ||||
|                         $returnValue += ($arg - $aMean) ** 2; | ||||
|                     } | ||||
|                     ++$aCount; | ||||
|                 } | ||||
| @ -3239,8 +3192,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        STDEVPA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float|string | ||||
| @ -3266,9 +3217,9 @@ class Statistical | ||||
|                             $arg = 0; | ||||
|                         } | ||||
|                         if ($returnValue === null) { | ||||
|                             $returnValue = pow(($arg - $aMean), 2); | ||||
|                             $returnValue = ($arg - $aMean) ** 2; | ||||
|                         } else { | ||||
|                             $returnValue += pow(($arg - $aMean), 2); | ||||
|                             $returnValue += ($arg - $aMean) ** 2; | ||||
|                         } | ||||
|                         ++$aCount; | ||||
|                     } | ||||
| @ -3477,10 +3428,7 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        TRIMEAN(value1[,value2[, ...]], $discard) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed $args Data values | ||||
|      * @param float $discard Percentage to discard | ||||
|      * | ||||
|      * @return float|string | ||||
|      */ | ||||
| @ -3523,8 +3471,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        VAR(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -3567,8 +3513,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        VARA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -3620,8 +3564,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        VARP(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -3665,8 +3607,6 @@ class Statistical | ||||
|      * Excel Function: | ||||
|      *        VARPA(value1[,value2[, ...]]) | ||||
|      * | ||||
|      * @category Statistical Functions | ||||
|      * | ||||
|      * @param mixed ...$args Data values | ||||
|      * | ||||
|      * @return float | ||||
| @ -3735,10 +3675,10 @@ class Statistical | ||||
|             } | ||||
|             if ((is_numeric($cumulative)) || (is_bool($cumulative))) { | ||||
|                 if ($cumulative) { | ||||
|                     return 1 - exp(0 - pow($value / $beta, $alpha)); | ||||
|                     return 1 - exp(0 - ($value / $beta) ** $alpha); | ||||
|                 } | ||||
| 
 | ||||
|                 return ($alpha / pow($beta, $alpha)) * pow($value, $alpha - 1) * exp(0 - pow($value / $beta, $alpha)); | ||||
|                 return ($alpha / $beta ** $alpha) * $value ** ($alpha - 1) * exp(0 - ($value / $beta) ** $alpha); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -167,7 +167,7 @@ class TextData | ||||
|         if ($decimals > 0) { | ||||
|             $mask .= '.' . str_repeat('0', $decimals); | ||||
|         } else { | ||||
|             $round = pow(10, abs($decimals)); | ||||
|             $round = 10 ** abs($decimals); | ||||
|             if ($value < 0) { | ||||
|                 $round = 0 - $round; | ||||
|             } | ||||
| @ -623,7 +623,7 @@ class TextData | ||||
|             $percentageAdjustment = strlen($value) - strlen($percentageString); | ||||
|             if ($percentageAdjustment) { | ||||
|                 $value = (float) $percentageString; | ||||
|                 $value /= pow(10, $percentageAdjustment * 2); | ||||
|                 $value /= 10 ** ($percentageAdjustment * 2); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -49,7 +49,7 @@ class Stack | ||||
|         $storeKey = null, | ||||
|         $onlyIf = null, | ||||
|         $onlyIfNot = null | ||||
|     ) { | ||||
|     ): void { | ||||
|         $stackItem = $this->getStackItem($type, $value, $reference, $storeKey, $onlyIf, $onlyIfNot); | ||||
| 
 | ||||
|         $this->stack[$this->count++] = $stackItem; | ||||
| @ -124,7 +124,7 @@ class Stack | ||||
|     /** | ||||
|      * Clear the stack. | ||||
|      */ | ||||
|     public function clear() | ||||
|     public function clear(): void | ||||
|     { | ||||
|         $this->stack = []; | ||||
|         $this->count = 0; | ||||
|  | ||||
| @ -316,6 +316,8 @@ SEC | ||||
| SECH | ||||
| SECOND | ||||
| SERIESSUM | ||||
| SHEET | ||||
| SHEETS | ||||
| SIGN | ||||
| SIN | ||||
| SINH | ||||
|  | ||||
| @ -16,8 +16,6 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder | ||||
|      * @param Cell $cell Cell to bind value to | ||||
|      * @param mixed $value Value to bind in cell | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function bindValue(Cell $cell, $value = null) | ||||
|  | ||||
| @ -76,12 +76,12 @@ class Cell | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function detach() | ||||
|     public function detach(): void | ||||
|     { | ||||
|         $this->parent = null; | ||||
|     } | ||||
| 
 | ||||
|     public function attach(Cells $parent) | ||||
|     public function attach(Cells $parent): void | ||||
|     { | ||||
|         $this->parent = $parent; | ||||
|     } | ||||
| @ -91,9 +91,6 @@ class Cell | ||||
|      * | ||||
|      * @param mixed $pValue | ||||
|      * @param string $pDataType | ||||
|      * @param Worksheet $pSheet | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function __construct($pValue, $pDataType, Worksheet $pSheet) | ||||
|     { | ||||
| @ -175,8 +172,6 @@ class Cell | ||||
|      * | ||||
|      * @param mixed $pValue Value | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setValue($pValue) | ||||
| @ -194,8 +189,6 @@ class Cell | ||||
|      * @param mixed $pValue Value | ||||
|      * @param string $pDataType Explicit data type, see DataType::TYPE_* | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Cell | ||||
|      */ | ||||
|     public function setValueExplicit($pValue, $pDataType) | ||||
| @ -252,8 +245,6 @@ class Cell | ||||
|      * | ||||
|      * @param bool $resetLog Whether the calculation engine logger should be reset or not | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getCalculatedValue($resetLog = true) | ||||
| @ -362,8 +353,6 @@ class Cell | ||||
|     /** | ||||
|      *    Does this cell contain Data validation rules? | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function hasDataValidation() | ||||
| @ -378,8 +367,6 @@ class Cell | ||||
|     /** | ||||
|      * Get Data validation rules. | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return DataValidation | ||||
|      */ | ||||
|     public function getDataValidation() | ||||
| @ -396,11 +383,9 @@ class Cell | ||||
|      * | ||||
|      * @param DataValidation $pDataValidation | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Cell | ||||
|      */ | ||||
|     public function setDataValidation(DataValidation $pDataValidation = null) | ||||
|     public function setDataValidation(?DataValidation $pDataValidation = null) | ||||
|     { | ||||
|         if (!isset($this->parent)) { | ||||
|             throw new Exception('Cannot set data validation for cell that is not bound to a worksheet'); | ||||
| @ -426,8 +411,6 @@ class Cell | ||||
|     /** | ||||
|      * Does this cell contain a Hyperlink? | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function hasHyperlink() | ||||
| @ -442,8 +425,6 @@ class Cell | ||||
|     /** | ||||
|      * Get Hyperlink. | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Hyperlink | ||||
|      */ | ||||
|     public function getHyperlink() | ||||
| @ -460,11 +441,9 @@ class Cell | ||||
|      * | ||||
|      * @param Hyperlink $pHyperlink | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Cell | ||||
|      */ | ||||
|     public function setHyperlink(Hyperlink $pHyperlink = null) | ||||
|     public function setHyperlink(?Hyperlink $pHyperlink = null) | ||||
|     { | ||||
|         if (!isset($this->parent)) { | ||||
|             throw new Exception('Cannot set hyperlink for cell that is not bound to a worksheet'); | ||||
| @ -552,8 +531,6 @@ class Cell | ||||
|     /** | ||||
|      * Re-bind parent. | ||||
|      * | ||||
|      * @param Worksheet $parent | ||||
|      * | ||||
|      * @return Cell | ||||
|      */ | ||||
|     public function rebindParent(Worksheet $parent) | ||||
| @ -620,10 +597,8 @@ class Cell | ||||
| 
 | ||||
|     /** | ||||
|      * Set value binder to use. | ||||
|      * | ||||
|      * @param IValueBinder $binder | ||||
|      */ | ||||
|     public static function setValueBinder(IValueBinder $binder) | ||||
|     public static function setValueBinder(IValueBinder $binder): void | ||||
|     { | ||||
|         self::$valueBinder = $binder; | ||||
|     } | ||||
|  | ||||
| @ -25,8 +25,6 @@ abstract class Coordinate | ||||
|      * | ||||
|      * @param string $pCoordinateString eg: 'A1' | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string[] Array containing column and row (indexes 0 and 1) | ||||
|      */ | ||||
|     public static function coordinateFromString($pCoordinateString) | ||||
| @ -60,8 +58,6 @@ abstract class Coordinate | ||||
|      * @param string $pCoordinateString e.g. 'A' or '1' or 'A1' | ||||
|      *                    Note that this value can be a row or column reference as well as a cell reference | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string Absolute coordinate        e.g. '$A' or '$1' or '$A$1' | ||||
|      */ | ||||
|     public static function absoluteReference($pCoordinateString) | ||||
| @ -91,8 +87,6 @@ abstract class Coordinate | ||||
|      * | ||||
|      * @param string $pCoordinateString e.g. 'A1' | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string Absolute coordinate        e.g. '$A$1' | ||||
|      */ | ||||
|     public static function absoluteCoordinate($pCoordinateString) | ||||
| @ -145,8 +139,6 @@ abstract class Coordinate | ||||
|      * | ||||
|      * @param array $pRange Array containg one or more arrays containing one or two coordinate strings | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string String representation of $pRange | ||||
|      */ | ||||
|     public static function buildRange(array $pRange) | ||||
| @ -511,7 +503,7 @@ abstract class Coordinate | ||||
|      * @param int $currentRow | ||||
|      * @param int $endRow | ||||
|      */ | ||||
|     private static function validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow) | ||||
|     private static function validateRange($cellBlock, $startColumnIndex, $endColumnIndex, $currentRow, $endRow): void | ||||
|     { | ||||
|         if ($startColumnIndex >= $endColumnIndex || $currentRow > $endRow) { | ||||
|             throw new Exception('Invalid range: "' . $cellBlock . '"'); | ||||
|  | ||||
| @ -14,8 +14,6 @@ class DefaultValueBinder implements IValueBinder | ||||
|      * @param Cell $cell Cell to bind value to | ||||
|      * @param mixed $value Value to bind in cell | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function bindValue(Cell $cell, $value) | ||||
|  | ||||
| @ -12,8 +12,6 @@ class StringValueBinder implements IValueBinder | ||||
|      * @param Cell $cell Cell to bind value to | ||||
|      * @param mixed $value Value to bind in cell | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function bindValue(Cell $cell, $value) | ||||
|  | ||||
| @ -178,7 +178,7 @@ class Axis extends Properties | ||||
|      * @param string $major_unit | ||||
|      * @param string $minor_unit | ||||
|      */ | ||||
|     public function setAxisOptionsProperties($axis_labels, $horizontal_crosses_value = null, $horizontal_crosses = null, $axis_orientation = null, $major_tmt = null, $minor_tmt = null, $minimum = null, $maximum = null, $major_unit = null, $minor_unit = null) | ||||
|     public function setAxisOptionsProperties($axis_labels, $horizontal_crosses_value = null, $horizontal_crosses = null, $axis_orientation = null, $major_tmt = null, $minor_tmt = null, $minimum = null, $maximum = null, $major_unit = null, $minor_unit = null): void | ||||
|     { | ||||
|         $this->axisOptions['axis_labels'] = (string) $axis_labels; | ||||
|         ($horizontal_crosses_value !== null) ? $this->axisOptions['horizontal_crosses_value'] = (string) $horizontal_crosses_value : null; | ||||
| @ -210,7 +210,7 @@ class Axis extends Properties | ||||
|      * | ||||
|      * @param string $orientation | ||||
|      */ | ||||
|     public function setAxisOrientation($orientation) | ||||
|     public function setAxisOrientation($orientation): void | ||||
|     { | ||||
|         $this->axisOptions['orientation'] = (string) $orientation; | ||||
|     } | ||||
| @ -222,7 +222,7 @@ class Axis extends Properties | ||||
|      * @param int $alpha | ||||
|      * @param string $type | ||||
|      */ | ||||
|     public function setFillParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB) | ||||
|     public function setFillParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB): void | ||||
|     { | ||||
|         $this->fillProperties = $this->setColorProperties($color, $alpha, $type); | ||||
|     } | ||||
| @ -234,7 +234,7 @@ class Axis extends Properties | ||||
|      * @param int $alpha | ||||
|      * @param string $type | ||||
|      */ | ||||
|     public function setLineParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB) | ||||
|     public function setLineParameters($color, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_ARGB): void | ||||
|     { | ||||
|         $this->lineProperties = $this->setColorProperties($color, $alpha, $type); | ||||
|     } | ||||
| @ -276,7 +276,7 @@ class Axis extends Properties | ||||
|      * @param string $end_arrow_type | ||||
|      * @param string $end_arrow_size | ||||
|      */ | ||||
|     public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null) | ||||
|     public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null): void | ||||
|     { | ||||
|         ($line_width !== null) ? $this->lineStyleProperties['width'] = $this->getExcelPointsWidth((float) $line_width) : null; | ||||
|         ($compound_type !== null) ? $this->lineStyleProperties['compound'] = (string) $compound_type : null; | ||||
| @ -336,7 +336,7 @@ class Axis extends Properties | ||||
|      * @param int $sh_angle | ||||
|      * @param float $sh_distance | ||||
|      */ | ||||
|     public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null) | ||||
|     public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null): void | ||||
|     { | ||||
|         $this->setShadowPresetsProperties((int) $sh_presets) | ||||
|             ->setShadowColor( | ||||
| @ -367,7 +367,6 @@ class Axis extends Properties | ||||
|     /** | ||||
|      * Set Shadow Properties from Mapped Values. | ||||
|      * | ||||
|      * @param array $properties_map | ||||
|      * @param mixed &$reference | ||||
|      * | ||||
|      * @return $this | ||||
| @ -479,7 +478,7 @@ class Axis extends Properties | ||||
|      * @param int $color_alpha | ||||
|      * @param string $color_type | ||||
|      */ | ||||
|     public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null) | ||||
|     public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null): void | ||||
|     { | ||||
|         $this->setGlowSize($size) | ||||
|             ->setGlowColor( | ||||
| @ -538,7 +537,7 @@ class Axis extends Properties | ||||
|      * | ||||
|      * @param float $size | ||||
|      */ | ||||
|     public function setSoftEdges($size) | ||||
|     public function setSoftEdges($size): void | ||||
|     { | ||||
|         if ($size !== null) { | ||||
|             $softEdges['size'] = (string) $this->getExcelPointsWidth($size); | ||||
|  | ||||
| @ -68,7 +68,7 @@ class Chart | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     private $displayBlanksAs = '0'; | ||||
|     private $displayBlanksAs = DataSeries::EMPTY_AS_GAP; | ||||
| 
 | ||||
|     /** | ||||
|      * Chart Asix Y as. | ||||
| @ -144,19 +144,10 @@ class Chart | ||||
|      * Create a new Chart. | ||||
|      * | ||||
|      * @param mixed $name | ||||
|      * @param null|Title $title | ||||
|      * @param null|Legend $legend | ||||
|      * @param null|PlotArea $plotArea | ||||
|      * @param mixed $plotVisibleOnly | ||||
|      * @param mixed $displayBlanksAs | ||||
|      * @param null|Title $xAxisLabel | ||||
|      * @param null|Title $yAxisLabel | ||||
|      * @param null|Axis $xAxis | ||||
|      * @param null|Axis $yAxis | ||||
|      * @param null|GridLines $majorGridlines | ||||
|      * @param null|GridLines $minorGridlines | ||||
|      * @param string $displayBlanksAs | ||||
|      */ | ||||
|     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) | ||||
|     public function __construct($name, ?Title $title = null, ?Legend $legend = null, ?PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = DataSeries::EMPTY_AS_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; | ||||
| @ -199,7 +190,7 @@ class Chart | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setWorksheet(Worksheet $pValue = null) | ||||
|     public function setWorksheet(?Worksheet $pValue = null) | ||||
|     { | ||||
|         $this->worksheet = $pValue; | ||||
| 
 | ||||
| @ -219,8 +210,6 @@ class Chart | ||||
|     /** | ||||
|      * Set Title. | ||||
|      * | ||||
|      * @param Title $title | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setTitle(Title $title) | ||||
| @ -243,8 +232,6 @@ class Chart | ||||
|     /** | ||||
|      * Set Legend. | ||||
|      * | ||||
|      * @param Legend $legend | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setLegend(Legend $legend) | ||||
| @ -267,8 +254,6 @@ class Chart | ||||
|     /** | ||||
|      * Set X-Axis Label. | ||||
|      * | ||||
|      * @param Title $label | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setXAxisLabel(Title $label) | ||||
| @ -291,8 +276,6 @@ class Chart | ||||
|     /** | ||||
|      * Set Y-Axis Label. | ||||
|      * | ||||
|      * @param Title $label | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setYAxisLabel(Title $label) | ||||
| @ -645,7 +628,7 @@ class Chart | ||||
|         return $this->bottomRightYOffset; | ||||
|     } | ||||
| 
 | ||||
|     public function refresh() | ||||
|     public function refresh(): void | ||||
|     { | ||||
|         if ($this->worksheet !== null) { | ||||
|             $this->plotArea->refresh($this->worksheet); | ||||
|  | ||||
| @ -40,6 +40,10 @@ class DataSeries | ||||
|     const STYLE_MARKER = 'marker'; | ||||
|     const STYLE_FILLED = 'filled'; | ||||
| 
 | ||||
|     const EMPTY_AS_GAP = 'gap'; | ||||
|     const EMPTY_AS_ZERO = 'zero'; | ||||
|     const EMPTY_AS_SPAN = 'span'; | ||||
| 
 | ||||
|     /** | ||||
|      * Series Plot Type. | ||||
|      * | ||||
| @ -369,7 +373,7 @@ class DataSeries | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function refresh(Worksheet $worksheet) | ||||
|     public function refresh(Worksheet $worksheet): void | ||||
|     { | ||||
|         foreach ($this->plotValues as $plotValues) { | ||||
|             if ($plotValues !== null) { | ||||
|  | ||||
| @ -115,8 +115,6 @@ class DataSeriesValues | ||||
|      *                                    DataSeriesValues::DATASERIES_TYPE_NUMBER | ||||
|      *                                        Normally used for chart data values | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setDataType($dataType) | ||||
| @ -247,8 +245,6 @@ class DataSeriesValues | ||||
|      * | ||||
|      * @param string $color value for color | ||||
|      * | ||||
|      * @throws \Exception thrown if color is invalid | ||||
|      * | ||||
|      * @return bool true if validation was successful | ||||
|      */ | ||||
|     private function validateColor($color) | ||||
| @ -356,7 +352,7 @@ class DataSeriesValues | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function refresh(Worksheet $worksheet, $flatten = true) | ||||
|     public function refresh(Worksheet $worksheet, $flatten = true): void | ||||
|     { | ||||
|         if ($this->dataSource !== null) { | ||||
|             $calcEngine = Calculation::getInstance($worksheet->getParent()); | ||||
|  | ||||
| @ -107,7 +107,7 @@ class GridLines extends Properties | ||||
|      * @param int $alpha | ||||
|      * @param string $type | ||||
|      */ | ||||
|     public function setLineColorProperties($value, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_STANDARD) | ||||
|     public function setLineColorProperties($value, $alpha = 0, $type = self::EXCEL_COLOR_TYPE_STANDARD): void | ||||
|     { | ||||
|         $this->activateObject() | ||||
|             ->lineProperties['color'] = $this->setColorProperties( | ||||
| @ -130,7 +130,7 @@ class GridLines extends Properties | ||||
|      * @param string $end_arrow_type | ||||
|      * @param string $end_arrow_size | ||||
|      */ | ||||
|     public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null) | ||||
|     public function setLineStyleProperties($line_width = null, $compound_type = null, $dash_type = null, $cap_type = null, $join_type = null, $head_arrow_type = null, $head_arrow_size = null, $end_arrow_type = null, $end_arrow_size = null): void | ||||
|     { | ||||
|         $this->activateObject(); | ||||
|         ($line_width !== null) | ||||
| @ -194,7 +194,7 @@ class GridLines extends Properties | ||||
|      * @param int $color_alpha | ||||
|      * @param string $color_type | ||||
|      */ | ||||
|     public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null) | ||||
|     public function setGlowProperties($size, $color_value = null, $color_alpha = null, $color_type = null): void | ||||
|     { | ||||
|         $this | ||||
|             ->activateObject() | ||||
| @ -286,7 +286,7 @@ class GridLines extends Properties | ||||
|      * @param int $sh_angle | ||||
|      * @param float $sh_distance | ||||
|      */ | ||||
|     public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null) | ||||
|     public function setShadowProperties($sh_presets, $sh_color_value = null, $sh_color_type = null, $sh_color_alpha = null, $sh_blur = null, $sh_angle = null, $sh_distance = null): void | ||||
|     { | ||||
|         $this->activateObject() | ||||
|             ->setShadowPresetsProperties((int) $sh_presets) | ||||
| @ -318,7 +318,6 @@ class GridLines extends Properties | ||||
|     /** | ||||
|      * Set Shadow Properties Values. | ||||
|      * | ||||
|      * @param array $properties_map | ||||
|      * @param mixed &$reference | ||||
|      * | ||||
|      * @return $this | ||||
| @ -435,7 +434,7 @@ class GridLines extends Properties | ||||
|      * | ||||
|      * @param float $size | ||||
|      */ | ||||
|     public function setSoftEdgesSize($size) | ||||
|     public function setSoftEdgesSize($size): void | ||||
|     { | ||||
|         if ($size !== null) { | ||||
|             $this->activateObject(); | ||||
|  | ||||
| @ -110,8 +110,6 @@ class Layout | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new Layout. | ||||
|      * | ||||
|      * @param array $layout | ||||
|      */ | ||||
|     public function __construct(array $layout = []) | ||||
|     { | ||||
|  | ||||
| @ -52,10 +52,9 @@ class Legend | ||||
|      * Create a new Legend. | ||||
|      * | ||||
|      * @param string $position | ||||
|      * @param null|Layout $layout | ||||
|      * @param bool $overlay | ||||
|      */ | ||||
|     public function __construct($position = self::POSITION_RIGHT, Layout $layout = null, $overlay = false) | ||||
|     public function __construct($position = self::POSITION_RIGHT, ?Layout $layout = null, $overlay = false) | ||||
|     { | ||||
|         $this->setPosition($position); | ||||
|         $this->layout = $layout; | ||||
|  | ||||
| @ -23,10 +23,9 @@ class PlotArea | ||||
|     /** | ||||
|      * Create a new PlotArea. | ||||
|      * | ||||
|      * @param null|Layout $layout | ||||
|      * @param DataSeries[] $plotSeries | ||||
|      */ | ||||
|     public function __construct(Layout $layout = null, array $plotSeries = []) | ||||
|     public function __construct(?Layout $layout = null, array $plotSeries = []) | ||||
|     { | ||||
|         $this->layout = $layout; | ||||
|         $this->plotSeries = $plotSeries; | ||||
| @ -103,7 +102,7 @@ class PlotArea | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|     public function refresh(Worksheet $worksheet) | ||||
|     public function refresh(Worksheet $worksheet): void | ||||
|     { | ||||
|         foreach ($this->plotSeries as $plotSeries) { | ||||
|             $plotSeries->refresh($worksheet); | ||||
|  | ||||
| @ -8,8 +8,6 @@ interface IRenderer | ||||
| { | ||||
|     /** | ||||
|      * IRenderer constructor. | ||||
|      * | ||||
|      * @param \PhpOffice\PhpSpreadsheet\Chart\Chart $chart | ||||
|      */ | ||||
|     public function __construct(Chart $chart); | ||||
| 
 | ||||
|  | ||||
| @ -2,8 +2,24 @@ | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Chart\Renderer; | ||||
| 
 | ||||
| use AccBarPlot; | ||||
| use AccLinePlot; | ||||
| use BarPlot; | ||||
| use ContourPlot; | ||||
| use Graph; | ||||
| use GroupBarPlot; | ||||
| use LinePlot; | ||||
| use PhpOffice\PhpSpreadsheet\Chart\Chart; | ||||
| use PhpOffice\PhpSpreadsheet\Style\NumberFormat; | ||||
| use PieGraph; | ||||
| use PiePlot; | ||||
| use PiePlot3D; | ||||
| use PiePlotC; | ||||
| use RadarGraph; | ||||
| use RadarPlot; | ||||
| use ScatterPlot; | ||||
| use Spline; | ||||
| use StockPlot; | ||||
| 
 | ||||
| require_once __DIR__ . '/Polyfill.php'; | ||||
| 
 | ||||
| @ -33,8 +49,6 @@ class JpGraph implements IRenderer | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new jpgraph. | ||||
|      * | ||||
|      * @param Chart $chart | ||||
|      */ | ||||
|     public function __construct(Chart $chart) | ||||
|     { | ||||
| @ -43,7 +57,7 @@ class JpGraph implements IRenderer | ||||
|         $this->chart = $chart; | ||||
|     } | ||||
| 
 | ||||
|     private static function init() | ||||
|     private static function init(): void | ||||
|     { | ||||
|         static $loaded = false; | ||||
|         if ($loaded) { | ||||
| @ -179,7 +193,7 @@ class JpGraph implements IRenderer | ||||
|         return $caption; | ||||
|     } | ||||
| 
 | ||||
|     private function renderTitle() | ||||
|     private function renderTitle(): void | ||||
|     { | ||||
|         $title = $this->getCaption($this->chart->getTitle()); | ||||
|         if ($title !== null) { | ||||
| @ -187,7 +201,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderLegend() | ||||
|     private function renderLegend(): void | ||||
|     { | ||||
|         $legend = $this->chart->getLegend(); | ||||
|         if ($legend !== null) { | ||||
| @ -220,9 +234,9 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderCartesianPlotArea($type = 'textlin') | ||||
|     private function renderCartesianPlotArea($type = 'textlin'): void | ||||
|     { | ||||
|         $this->graph = new \Graph(self::$width, self::$height); | ||||
|         $this->graph = new Graph(self::$width, self::$height); | ||||
|         $this->graph->SetScale($type); | ||||
| 
 | ||||
|         $this->renderTitle(); | ||||
| @ -257,22 +271,22 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderPiePlotArea() | ||||
|     private function renderPiePlotArea(): void | ||||
|     { | ||||
|         $this->graph = new \PieGraph(self::$width, self::$height); | ||||
|         $this->graph = new PieGraph(self::$width, self::$height); | ||||
| 
 | ||||
|         $this->renderTitle(); | ||||
|     } | ||||
| 
 | ||||
|     private function renderRadarPlotArea() | ||||
|     private function renderRadarPlotArea(): void | ||||
|     { | ||||
|         $this->graph = new \RadarGraph(self::$width, self::$height); | ||||
|         $this->graph = new RadarGraph(self::$width, self::$height); | ||||
|         $this->graph->SetScale('lin'); | ||||
| 
 | ||||
|         $this->renderTitle(); | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') | ||||
|     private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d'): void | ||||
|     { | ||||
|         $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | ||||
| 
 | ||||
| @ -308,7 +322,7 @@ class JpGraph implements IRenderer | ||||
|                 ++$testCurrentIndex; | ||||
|             } | ||||
| 
 | ||||
|             $seriesPlot = new \LinePlot($dataValues); | ||||
|             $seriesPlot = new LinePlot($dataValues); | ||||
|             if ($combination) { | ||||
|                 $seriesPlot->SetBarCenter(); | ||||
|             } | ||||
| @ -330,12 +344,12 @@ class JpGraph implements IRenderer | ||||
|         if ($grouping == 'standard') { | ||||
|             $groupPlot = $seriesPlots; | ||||
|         } else { | ||||
|             $groupPlot = new \AccLinePlot($seriesPlots); | ||||
|             $groupPlot = new AccLinePlot($seriesPlots); | ||||
|         } | ||||
|         $this->graph->Add($groupPlot); | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotBar($groupID, $dimensions = '2d') | ||||
|     private function renderPlotBar($groupID, $dimensions = '2d'): void | ||||
|     { | ||||
|         $rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection(); | ||||
|         //    Rotate for bar rather than column chart
 | ||||
| @ -385,7 +399,7 @@ class JpGraph implements IRenderer | ||||
|             if ($rotation == 'bar') { | ||||
|                 $dataValues = array_reverse($dataValues); | ||||
|             } | ||||
|             $seriesPlot = new \BarPlot($dataValues); | ||||
|             $seriesPlot = new BarPlot($dataValues); | ||||
|             $seriesPlot->SetColor('black'); | ||||
|             $seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]); | ||||
|             if ($dimensions == '3d') { | ||||
| @ -406,11 +420,11 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
| 
 | ||||
|         if ($grouping == 'clustered') { | ||||
|             $groupPlot = new \GroupBarPlot($seriesPlots); | ||||
|             $groupPlot = new GroupBarPlot($seriesPlots); | ||||
|         } elseif ($grouping == 'standard') { | ||||
|             $groupPlot = new \GroupBarPlot($seriesPlots); | ||||
|             $groupPlot = new GroupBarPlot($seriesPlots); | ||||
|         } else { | ||||
|             $groupPlot = new \AccBarPlot($seriesPlots); | ||||
|             $groupPlot = new AccBarPlot($seriesPlots); | ||||
|             if ($dimensions == '3d') { | ||||
|                 $groupPlot->SetShadow(); | ||||
|             } | ||||
| @ -419,7 +433,7 @@ class JpGraph implements IRenderer | ||||
|         $this->graph->Add($groupPlot); | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotScatter($groupID, $bubble) | ||||
|     private function renderPlotScatter($groupID, $bubble): void | ||||
|     { | ||||
|         $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); | ||||
|         $scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | ||||
| @ -436,14 +450,14 @@ class JpGraph implements IRenderer | ||||
|                 $dataValuesY[$k] = $k; | ||||
|             } | ||||
| 
 | ||||
|             $seriesPlot = new \ScatterPlot($dataValuesX, $dataValuesY); | ||||
|             $seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY); | ||||
|             if ($scatterStyle == 'lineMarker') { | ||||
|                 $seriesPlot->SetLinkPoints(); | ||||
|                 $seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]); | ||||
|             } elseif ($scatterStyle == 'smoothMarker') { | ||||
|                 $spline = new \Spline($dataValuesY, $dataValuesX); | ||||
|                 $spline = new Spline($dataValuesY, $dataValuesX); | ||||
|                 [$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20); | ||||
|                 $lplot = new \LinePlot($splineDataX, $splineDataY); | ||||
|                 $lplot = new LinePlot($splineDataX, $splineDataY); | ||||
|                 $lplot->SetColor(self::$colourSet[self::$plotColour]); | ||||
| 
 | ||||
|                 $this->graph->Add($lplot); | ||||
| @ -464,7 +478,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotRadar($groupID) | ||||
|     private function renderPlotRadar($groupID): void | ||||
|     { | ||||
|         $radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | ||||
| 
 | ||||
| @ -488,7 +502,7 @@ class JpGraph implements IRenderer | ||||
| 
 | ||||
|             $this->graph->SetTitles(array_reverse($dataValues)); | ||||
| 
 | ||||
|             $seriesPlot = new \RadarPlot(array_reverse($dataValuesX)); | ||||
|             $seriesPlot = new RadarPlot(array_reverse($dataValuesX)); | ||||
| 
 | ||||
|             $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); | ||||
|             $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); | ||||
| @ -502,7 +516,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotContour($groupID) | ||||
|     private function renderPlotContour($groupID): void | ||||
|     { | ||||
|         $contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); | ||||
| 
 | ||||
| @ -517,12 +531,12 @@ class JpGraph implements IRenderer | ||||
| 
 | ||||
|             $dataValues[$i] = $dataValuesX; | ||||
|         } | ||||
|         $seriesPlot = new \ContourPlot($dataValues); | ||||
|         $seriesPlot = new ContourPlot($dataValues); | ||||
| 
 | ||||
|         $this->graph->Add($seriesPlot); | ||||
|     } | ||||
| 
 | ||||
|     private function renderPlotStock($groupID) | ||||
|     private function renderPlotStock($groupID): void | ||||
|     { | ||||
|         $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); | ||||
|         $plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder(); | ||||
| @ -556,13 +570,13 @@ class JpGraph implements IRenderer | ||||
|             $this->graph->xaxis->SetTickLabels($datasetLabels); | ||||
|         } | ||||
| 
 | ||||
|         $seriesPlot = new \StockPlot($dataValuesPlot); | ||||
|         $seriesPlot = new StockPlot($dataValuesPlot); | ||||
|         $seriesPlot->SetWidth(20); | ||||
| 
 | ||||
|         $this->graph->Add($seriesPlot); | ||||
|     } | ||||
| 
 | ||||
|     private function renderAreaChart($groupCount, $dimensions = '2d') | ||||
|     private function renderAreaChart($groupCount, $dimensions = '2d'): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea(); | ||||
| 
 | ||||
| @ -571,7 +585,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderLineChart($groupCount, $dimensions = '2d') | ||||
|     private function renderLineChart($groupCount, $dimensions = '2d'): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea(); | ||||
| 
 | ||||
| @ -580,7 +594,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderBarChart($groupCount, $dimensions = '2d') | ||||
|     private function renderBarChart($groupCount, $dimensions = '2d'): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea(); | ||||
| 
 | ||||
| @ -589,7 +603,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderScatterChart($groupCount) | ||||
|     private function renderScatterChart($groupCount): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea('linlin'); | ||||
| 
 | ||||
| @ -598,7 +612,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderBubbleChart($groupCount) | ||||
|     private function renderBubbleChart($groupCount): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea('linlin'); | ||||
| 
 | ||||
| @ -607,7 +621,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false) | ||||
|     private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false): void | ||||
|     { | ||||
|         $this->renderPiePlotArea(); | ||||
| 
 | ||||
| @ -643,12 +657,12 @@ class JpGraph implements IRenderer | ||||
|                 } | ||||
| 
 | ||||
|                 if ($dimensions == '3d') { | ||||
|                     $seriesPlot = new \PiePlot3D($dataValues); | ||||
|                     $seriesPlot = new PiePlot3D($dataValues); | ||||
|                 } else { | ||||
|                     if ($doughnut) { | ||||
|                         $seriesPlot = new \PiePlotC($dataValues); | ||||
|                         $seriesPlot = new PiePlotC($dataValues); | ||||
|                     } else { | ||||
|                         $seriesPlot = new \PiePlot($dataValues); | ||||
|                         $seriesPlot = new PiePlot($dataValues); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
| @ -679,7 +693,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderRadarChart($groupCount) | ||||
|     private function renderRadarChart($groupCount): void | ||||
|     { | ||||
|         $this->renderRadarPlotArea(); | ||||
| 
 | ||||
| @ -688,7 +702,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderStockChart($groupCount) | ||||
|     private function renderStockChart($groupCount): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea('intint'); | ||||
| 
 | ||||
| @ -697,7 +711,7 @@ class JpGraph implements IRenderer | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function renderContourChart($groupCount, $dimensions) | ||||
|     private function renderContourChart($groupCount, $dimensions): void | ||||
|     { | ||||
|         $this->renderCartesianPlotArea('intint'); | ||||
| 
 | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| // This is a dirty workaround to output JpGraph charts even when antialiasing is not available
 | ||||
| if (!function_exists('imageantialias')) { | ||||
|     function imageantialias(...$args) | ||||
|     function imageantialias(...$args): void | ||||
|     { | ||||
|         // Do nothing
 | ||||
|     } | ||||
|  | ||||
| @ -22,9 +22,8 @@ class Title | ||||
|      * Create a new Title. | ||||
|      * | ||||
|      * @param null|mixed $caption | ||||
|      * @param null|Layout $layout | ||||
|      */ | ||||
|     public function __construct($caption = null, Layout $layout = null) | ||||
|     public function __construct($caption = null, ?Layout $layout = null) | ||||
|     { | ||||
|         $this->caption = $caption; | ||||
|         $this->layout = $layout; | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Collection; | ||||
| 
 | ||||
| use Generator; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\Cell; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\Coordinate; | ||||
| use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException; | ||||
| @ -61,7 +62,6 @@ class Cells | ||||
|      * Initialise this new cell collection. | ||||
|      * | ||||
|      * @param Worksheet $parent The worksheet for this cell collection | ||||
|      * @param CacheInterface $cache | ||||
|      */ | ||||
|     public function __construct(Worksheet $parent, CacheInterface $cache) | ||||
|     { | ||||
| @ -105,8 +105,6 @@ class Cells | ||||
|      * | ||||
|      * @param Cell $cell Cell to update | ||||
|      * | ||||
|      * @throws PhpSpreadsheetException | ||||
|      * | ||||
|      * @return Cell | ||||
|      */ | ||||
|     public function update(Cell $cell) | ||||
| @ -119,7 +117,7 @@ class Cells | ||||
|      * | ||||
|      * @param string $pCoord Coordinate of the cell to delete | ||||
|      */ | ||||
|     public function delete($pCoord) | ||||
|     public function delete($pCoord): void | ||||
|     { | ||||
|         if ($pCoord === $this->currentCoordinate && $this->currentCell !== null) { | ||||
|             $this->currentCell->detach(); | ||||
| @ -348,7 +346,7 @@ class Cells | ||||
|      * | ||||
|      * @param string $row Row number to remove | ||||
|      */ | ||||
|     public function removeRow($row) | ||||
|     public function removeRow($row): void | ||||
|     { | ||||
|         foreach ($this->getCoordinates() as $coord) { | ||||
|             $c = ''; | ||||
| @ -366,7 +364,7 @@ class Cells | ||||
|      * | ||||
|      * @param string $column Column ID to remove | ||||
|      */ | ||||
|     public function removeColumn($column) | ||||
|     public function removeColumn($column): void | ||||
|     { | ||||
|         foreach ($this->getCoordinates() as $coord) { | ||||
|             $c = ''; | ||||
| @ -382,10 +380,8 @@ class Cells | ||||
|     /** | ||||
|      * Store cell data in cache for the current cell object if it's "dirty", | ||||
|      * and the 'nullify' the current cell object. | ||||
|      * | ||||
|      * @throws PhpSpreadsheetException | ||||
|      */ | ||||
|     private function storeCurrentCell() | ||||
|     private function storeCurrentCell(): void | ||||
|     { | ||||
|         if ($this->currentCellIsDirty && !empty($this->currentCoordinate)) { | ||||
|             $this->currentCell->detach(); | ||||
| @ -409,8 +405,6 @@ class Cells | ||||
|      * @param string $pCoord Coordinate of the cell to update | ||||
|      * @param Cell $cell Cell to update | ||||
|      * | ||||
|      * @throws PhpSpreadsheetException | ||||
|      * | ||||
|      * @return \PhpOffice\PhpSpreadsheet\Cell\Cell | ||||
|      */ | ||||
|     public function add($pCoord, Cell $cell) | ||||
| @ -432,9 +426,7 @@ class Cells | ||||
|      * | ||||
|      * @param string $pCoord Coordinate of the cell | ||||
|      * | ||||
|      * @throws PhpSpreadsheetException | ||||
|      * | ||||
|      * @return \PhpOffice\PhpSpreadsheet\Cell\Cell Cell that was found, or null if not found | ||||
|      * @return null|\PhpOffice\PhpSpreadsheet\Cell\Cell Cell that was found, or null if not found | ||||
|      */ | ||||
|     public function get($pCoord) | ||||
|     { | ||||
| @ -467,7 +459,7 @@ class Cells | ||||
|     /** | ||||
|      * Clear the cell collection and disconnect from our parent. | ||||
|      */ | ||||
|     public function unsetWorksheetCells() | ||||
|     public function unsetWorksheetCells(): void | ||||
|     { | ||||
|         if ($this->currentCell !== null) { | ||||
|             $this->currentCell->detach(); | ||||
| @ -495,7 +487,7 @@ class Cells | ||||
|     /** | ||||
|      * Returns all known cache keys. | ||||
|      * | ||||
|      * @return \Generator|string[] | ||||
|      * @return Generator|string[] | ||||
|      */ | ||||
|     private function getAllCacheKeys() | ||||
|     { | ||||
|  | ||||
| @ -118,8 +118,6 @@ class Comment implements IComparable | ||||
|     /** | ||||
|      * Set Rich text comment. | ||||
|      * | ||||
|      * @param RichText $pValue | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setText(RichText $pValue) | ||||
|  | ||||
| @ -458,10 +458,10 @@ class Properties | ||||
|     public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) | ||||
|     { | ||||
|         if (($propertyType === null) || (!in_array($propertyType, [self::PROPERTY_TYPE_INTEGER, | ||||
|                                                                         self::PROPERTY_TYPE_FLOAT, | ||||
|                                                                         self::PROPERTY_TYPE_STRING, | ||||
|                                                                         self::PROPERTY_TYPE_DATE, | ||||
|                                                                         self::PROPERTY_TYPE_BOOLEAN, ]))) { | ||||
|             self::PROPERTY_TYPE_FLOAT, | ||||
|             self::PROPERTY_TYPE_STRING, | ||||
|             self::PROPERTY_TYPE_DATE, | ||||
|             self::PROPERTY_TYPE_BOOLEAN, ]))) { | ||||
|             if ($propertyValue === null) { | ||||
|                 $propertyType = self::PROPERTY_TYPE_STRING; | ||||
|             } elseif (is_float($propertyValue)) { | ||||
|  | ||||
| @ -5,17 +5,12 @@ namespace PhpOffice\PhpSpreadsheet; | ||||
| use PhpOffice\PhpSpreadsheet\Calculation\Category; | ||||
| use PhpOffice\PhpSpreadsheet\Calculation\Functions; | ||||
| use ReflectionClass; | ||||
| use ReflectionException; | ||||
| use UnexpectedValueException; | ||||
| 
 | ||||
| class DocumentGenerator | ||||
| { | ||||
|     /** | ||||
|      * @param array[] $phpSpreadsheetFunctions | ||||
|      * | ||||
|      * @throws ReflectionException | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function generateFunctionListByCategory(array $phpSpreadsheetFunctions): string | ||||
|     { | ||||
| @ -38,17 +33,12 @@ class DocumentGenerator | ||||
|         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 | ||||
|     private static function tableRow(array $lengths, ?array $values = null): string | ||||
|     { | ||||
|         $result = ''; | ||||
|         foreach (array_map(null, $lengths, $values ?? []) as $i => [$length, $value]) { | ||||
| @ -81,10 +71,6 @@ class DocumentGenerator | ||||
| 
 | ||||
|     /** | ||||
|      * @param array[] $phpSpreadsheetFunctions | ||||
|      * | ||||
|      * @throws ReflectionException | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function generateFunctionListByName(array $phpSpreadsheetFunctions): string | ||||
|     { | ||||
|  | ||||
| @ -22,8 +22,6 @@ class HashTable | ||||
|      * Create a new \PhpOffice\PhpSpreadsheet\HashTable. | ||||
|      * | ||||
|      * @param IComparable[] $pSource Optional source array to create HashTable from | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function __construct($pSource = null) | ||||
|     { | ||||
| @ -37,10 +35,8 @@ class HashTable | ||||
|      * Add HashTable items from source. | ||||
|      * | ||||
|      * @param IComparable[] $pSource Source array to create HashTable from | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function addFromSource(array $pSource = null) | ||||
|     public function addFromSource(?array $pSource = null): void | ||||
|     { | ||||
|         // Check if an array was passed
 | ||||
|         if ($pSource == null) { | ||||
| @ -57,7 +53,7 @@ class HashTable | ||||
|      * | ||||
|      * @param IComparable $pSource Item to add | ||||
|      */ | ||||
|     public function add(IComparable $pSource) | ||||
|     public function add(IComparable $pSource): void | ||||
|     { | ||||
|         $hash = $pSource->getHashCode(); | ||||
|         if (!isset($this->items[$hash])) { | ||||
| @ -71,7 +67,7 @@ class HashTable | ||||
|      * | ||||
|      * @param IComparable $pSource Item to remove | ||||
|      */ | ||||
|     public function remove(IComparable $pSource) | ||||
|     public function remove(IComparable $pSource): void | ||||
|     { | ||||
|         $hash = $pSource->getHashCode(); | ||||
|         if (isset($this->items[$hash])) { | ||||
| @ -94,7 +90,7 @@ class HashTable | ||||
|     /** | ||||
|      * Clear HashTable. | ||||
|      */ | ||||
|     public function clear() | ||||
|     public function clear(): void | ||||
|     { | ||||
|         $this->items = []; | ||||
|         $this->keyMap = []; | ||||
|  | ||||
| @ -593,7 +593,7 @@ class Html | ||||
|      */ | ||||
|     protected $richTextObject; | ||||
| 
 | ||||
|     protected function initialise() | ||||
|     protected function initialise(): void | ||||
|     { | ||||
|         $this->face = $this->size = $this->color = null; | ||||
|         $this->bold = $this->italic = $this->underline = $this->superscript = $this->subscript = $this->strikethrough = false; | ||||
| @ -632,7 +632,7 @@ class Html | ||||
|         return $this->richTextObject; | ||||
|     } | ||||
| 
 | ||||
|     protected function cleanWhitespace() | ||||
|     protected function cleanWhitespace(): void | ||||
|     { | ||||
|         foreach ($this->richTextObject->getRichTextElements() as $key => $element) { | ||||
|             $text = $element->getText(); | ||||
| @ -646,7 +646,7 @@ class Html | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected function buildTextRun() | ||||
|     protected function buildTextRun(): void | ||||
|     { | ||||
|         $text = $this->stringData; | ||||
|         if (trim($text) === '') { | ||||
| @ -691,7 +691,7 @@ class Html | ||||
|             $value = str_pad(dechex($value), 2, '0', STR_PAD_LEFT); | ||||
|         } | ||||
| 
 | ||||
|         return implode($values[0]); | ||||
|         return implode('', $values[0]); | ||||
|     } | ||||
| 
 | ||||
|     protected function colourNameLookup($rgb) | ||||
| @ -699,7 +699,7 @@ class Html | ||||
|         return self::$colourMap[$rgb]; | ||||
|     } | ||||
| 
 | ||||
|     protected function startFontTag($tag) | ||||
|     protected function startFontTag($tag): void | ||||
|     { | ||||
|         foreach ($tag->attributes as $attribute) { | ||||
|             $attributeName = strtolower($attribute->name); | ||||
| @ -719,77 +719,77 @@ class Html | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected function endFontTag() | ||||
|     protected function endFontTag(): void | ||||
|     { | ||||
|         $this->face = $this->size = $this->color = null; | ||||
|     } | ||||
| 
 | ||||
|     protected function startBoldTag() | ||||
|     protected function startBoldTag(): void | ||||
|     { | ||||
|         $this->bold = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endBoldTag() | ||||
|     protected function endBoldTag(): void | ||||
|     { | ||||
|         $this->bold = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function startItalicTag() | ||||
|     protected function startItalicTag(): void | ||||
|     { | ||||
|         $this->italic = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endItalicTag() | ||||
|     protected function endItalicTag(): void | ||||
|     { | ||||
|         $this->italic = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function startUnderlineTag() | ||||
|     protected function startUnderlineTag(): void | ||||
|     { | ||||
|         $this->underline = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endUnderlineTag() | ||||
|     protected function endUnderlineTag(): void | ||||
|     { | ||||
|         $this->underline = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function startSubscriptTag() | ||||
|     protected function startSubscriptTag(): void | ||||
|     { | ||||
|         $this->subscript = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endSubscriptTag() | ||||
|     protected function endSubscriptTag(): void | ||||
|     { | ||||
|         $this->subscript = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function startSuperscriptTag() | ||||
|     protected function startSuperscriptTag(): void | ||||
|     { | ||||
|         $this->superscript = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endSuperscriptTag() | ||||
|     protected function endSuperscriptTag(): void | ||||
|     { | ||||
|         $this->superscript = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function startStrikethruTag() | ||||
|     protected function startStrikethruTag(): void | ||||
|     { | ||||
|         $this->strikethrough = true; | ||||
|     } | ||||
| 
 | ||||
|     protected function endStrikethruTag() | ||||
|     protected function endStrikethruTag(): void | ||||
|     { | ||||
|         $this->strikethrough = false; | ||||
|     } | ||||
| 
 | ||||
|     protected function breakTag() | ||||
|     protected function breakTag(): void | ||||
|     { | ||||
|         $this->stringData .= "\n"; | ||||
|     } | ||||
| 
 | ||||
|     protected function parseTextNode(DOMText $textNode) | ||||
|     protected function parseTextNode(DOMText $textNode): void | ||||
|     { | ||||
|         $domText = preg_replace( | ||||
|             '/\s+/u', | ||||
| @ -801,11 +801,9 @@ class Html | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param DOMElement $element | ||||
|      * @param string $callbackTag | ||||
|      * @param array $callbacks | ||||
|      */ | ||||
|     protected function handleCallback(DOMElement $element, $callbackTag, array $callbacks) | ||||
|     protected function handleCallback(DOMElement $element, $callbackTag, array $callbacks): void | ||||
|     { | ||||
|         if (isset($callbacks[$callbackTag])) { | ||||
|             $elementHandler = $callbacks[$callbackTag]; | ||||
| @ -815,7 +813,7 @@ class Html | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected function parseElementNode(DOMElement $element) | ||||
|     protected function parseElementNode(DOMElement $element): void | ||||
|     { | ||||
|         $callbackTag = strtolower($element->nodeName); | ||||
|         $this->stack[] = $callbackTag; | ||||
| @ -828,7 +826,7 @@ class Html | ||||
|         $this->handleCallback($element, $callbackTag, $this->endTagCallbacks); | ||||
|     } | ||||
| 
 | ||||
|     protected function parseElements(DOMNode $element) | ||||
|     protected function parseElements(DOMNode $element): void | ||||
|     { | ||||
|         foreach ($element->childNodes as $child) { | ||||
|             if ($child instanceof DOMText) { | ||||
|  | ||||
| @ -1,333 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Helper; | ||||
| 
 | ||||
| class Migrator | ||||
| { | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private $from; | ||||
| 
 | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private $to; | ||||
| 
 | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->from = array_keys($this->getMapping()); | ||||
|         $this->to = array_values($this->getMapping()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Return the ordered mapping from old PHPExcel class names to new PhpSpreadsheet one. | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getMapping() | ||||
|     { | ||||
|         // Order matters here, we should have the deepest namespaces first (the most "unique" strings)
 | ||||
|         $classes = [ | ||||
|             'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE\Blip::class, | ||||
|             'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer\SpContainer::class, | ||||
|             'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer\BSE::class, | ||||
|             'PHPExcel_Shared_Escher_DgContainer_SpgrContainer' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer\SpgrContainer::class, | ||||
|             'PHPExcel_Shared_Escher_DggContainer_BstoreContainer' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer\BstoreContainer::class, | ||||
|             'PHPExcel_Shared_OLE_PPS_File' => \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\File::class, | ||||
|             'PHPExcel_Shared_OLE_PPS_Root' => \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS\Root::class, | ||||
|             'PHPExcel_Worksheet_AutoFilter_Column_Rule' => \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Cell_Comment' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Cell\Comment::class, | ||||
|             'PHPExcel_Calculation_Token_Stack' => \PhpOffice\PhpSpreadsheet\Calculation\Token\Stack::class, | ||||
|             'PHPExcel_Chart_Renderer_jpgraph' => \PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class, | ||||
|             'PHPExcel_Reader_Excel5_Escher' => \PhpOffice\PhpSpreadsheet\Reader\Xls\Escher::class, | ||||
|             'PHPExcel_Reader_Excel5_MD5' => \PhpOffice\PhpSpreadsheet\Reader\Xls\MD5::class, | ||||
|             'PHPExcel_Reader_Excel5_RC4' => \PhpOffice\PhpSpreadsheet\Reader\Xls\RC4::class, | ||||
|             'PHPExcel_Reader_Excel2007_Chart' => \PhpOffice\PhpSpreadsheet\Reader\Xlsx\Chart::class, | ||||
|             'PHPExcel_Reader_Excel2007_Theme' => \PhpOffice\PhpSpreadsheet\Reader\Xlsx\Theme::class, | ||||
|             'PHPExcel_Shared_Escher_DgContainer' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DgContainer::class, | ||||
|             'PHPExcel_Shared_Escher_DggContainer' => \PhpOffice\PhpSpreadsheet\Shared\Escher\DggContainer::class, | ||||
|             'CholeskyDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\CholeskyDecomposition::class, | ||||
|             'EigenvalueDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\EigenvalueDecomposition::class, | ||||
|             'PHPExcel_Shared_JAMA_LUDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\LUDecomposition::class, | ||||
|             'PHPExcel_Shared_JAMA_Matrix' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\Matrix::class, | ||||
|             'QRDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\QRDecomposition::class, | ||||
|             'PHPExcel_Shared_JAMA_QRDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\QRDecomposition::class, | ||||
|             'SingularValueDecomposition' => \PhpOffice\PhpSpreadsheet\Shared\JAMA\SingularValueDecomposition::class, | ||||
|             'PHPExcel_Shared_OLE_ChainedBlockStream' => \PhpOffice\PhpSpreadsheet\Shared\OLE\ChainedBlockStream::class, | ||||
|             'PHPExcel_Shared_OLE_PPS' => \PhpOffice\PhpSpreadsheet\Shared\OLE\PPS::class, | ||||
|             'PHPExcel_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\BestFit::class, | ||||
|             'PHPExcel_Exponential_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\ExponentialBestFit::class, | ||||
|             'PHPExcel_Linear_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\LinearBestFit::class, | ||||
|             'PHPExcel_Logarithmic_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\LogarithmicBestFit::class, | ||||
|             'polynomialBestFit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\PolynomialBestFit::class, | ||||
|             'PHPExcel_Polynomial_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\PolynomialBestFit::class, | ||||
|             'powerBestFit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\PowerBestFit::class, | ||||
|             'PHPExcel_Power_Best_Fit' => \PhpOffice\PhpSpreadsheet\Shared\Trend\PowerBestFit::class, | ||||
|             'trendClass' => \PhpOffice\PhpSpreadsheet\Shared\Trend\Trend::class, | ||||
|             'PHPExcel_Worksheet_AutoFilter_Column' => \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::class, | ||||
|             'PHPExcel_Worksheet_Drawing_Shadow' => \PhpOffice\PhpSpreadsheet\Worksheet\Drawing\Shadow::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Content' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Content::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Meta' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Meta::class, | ||||
|             'PHPExcel_Writer_OpenDocument_MetaInf' => \PhpOffice\PhpSpreadsheet\Writer\Ods\MetaInf::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Mimetype' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Settings' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Settings::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Styles' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Styles::class, | ||||
|             'PHPExcel_Writer_OpenDocument_Thumbnails' => \PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails::class, | ||||
|             'PHPExcel_Writer_OpenDocument_WriterPart' => \PhpOffice\PhpSpreadsheet\Writer\Ods\WriterPart::class, | ||||
|             'PHPExcel_Writer_PDF_Core' => \PhpOffice\PhpSpreadsheet\Writer\Pdf::class, | ||||
|             'PHPExcel_Writer_PDF_DomPDF' => \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class, | ||||
|             'PHPExcel_Writer_PDF_mPDF' => \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class, | ||||
|             'PHPExcel_Writer_PDF_tcPDF' => \PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf::class, | ||||
|             'PHPExcel_Writer_Excel5_BIFFwriter' => \PhpOffice\PhpSpreadsheet\Writer\Xls\BIFFwriter::class, | ||||
|             'PHPExcel_Writer_Excel5_Escher' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Escher::class, | ||||
|             'PHPExcel_Writer_Excel5_Font' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Font::class, | ||||
|             'PHPExcel_Writer_Excel5_Parser' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Parser::class, | ||||
|             'PHPExcel_Writer_Excel5_Workbook' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Workbook::class, | ||||
|             'PHPExcel_Writer_Excel5_Worksheet' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Worksheet::class, | ||||
|             'PHPExcel_Writer_Excel5_Xf' => \PhpOffice\PhpSpreadsheet\Writer\Xls\Xf::class, | ||||
|             'PHPExcel_Writer_Excel2007_Chart' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Chart::class, | ||||
|             'PHPExcel_Writer_Excel2007_Comments' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Comments::class, | ||||
|             'PHPExcel_Writer_Excel2007_ContentTypes' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\ContentTypes::class, | ||||
|             'PHPExcel_Writer_Excel2007_DocProps' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\DocProps::class, | ||||
|             'PHPExcel_Writer_Excel2007_Drawing' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Drawing::class, | ||||
|             'PHPExcel_Writer_Excel2007_Rels' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Rels::class, | ||||
|             'PHPExcel_Writer_Excel2007_RelsRibbon' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsRibbon::class, | ||||
|             'PHPExcel_Writer_Excel2007_RelsVBA' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\RelsVBA::class, | ||||
|             'PHPExcel_Writer_Excel2007_StringTable' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\StringTable::class, | ||||
|             'PHPExcel_Writer_Excel2007_Style' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Style::class, | ||||
|             'PHPExcel_Writer_Excel2007_Theme' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Theme::class, | ||||
|             'PHPExcel_Writer_Excel2007_Workbook' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook::class, | ||||
|             'PHPExcel_Writer_Excel2007_Worksheet' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::class, | ||||
|             'PHPExcel_Writer_Excel2007_WriterPart' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx\WriterPart::class, | ||||
|             'PHPExcel_CachedObjectStorage_CacheBase' => \PhpOffice\PhpSpreadsheet\Collection\Cells::class, | ||||
|             'PHPExcel_CalcEngine_CyclicReferenceStack' => \PhpOffice\PhpSpreadsheet\Calculation\Engine\CyclicReferenceStack::class, | ||||
|             'PHPExcel_CalcEngine_Logger' => \PhpOffice\PhpSpreadsheet\Calculation\Engine\Logger::class, | ||||
|             'PHPExcel_Calculation_Functions' => \PhpOffice\PhpSpreadsheet\Calculation\Functions::class, | ||||
|             'PHPExcel_Calculation_Function' => \PhpOffice\PhpSpreadsheet\Calculation\Category::class, | ||||
|             'PHPExcel_Calculation_Database' => \PhpOffice\PhpSpreadsheet\Calculation\Database::class, | ||||
|             'PHPExcel_Calculation_DateTime' => \PhpOffice\PhpSpreadsheet\Calculation\DateTime::class, | ||||
|             'PHPExcel_Calculation_Engineering' => \PhpOffice\PhpSpreadsheet\Calculation\Engineering::class, | ||||
|             'PHPExcel_Calculation_Exception' => \PhpOffice\PhpSpreadsheet\Calculation\Exception::class, | ||||
|             'PHPExcel_Calculation_ExceptionHandler' => \PhpOffice\PhpSpreadsheet\Calculation\ExceptionHandler::class, | ||||
|             'PHPExcel_Calculation_Financial' => \PhpOffice\PhpSpreadsheet\Calculation\Financial::class, | ||||
|             'PHPExcel_Calculation_FormulaParser' => \PhpOffice\PhpSpreadsheet\Calculation\FormulaParser::class, | ||||
|             'PHPExcel_Calculation_FormulaToken' => \PhpOffice\PhpSpreadsheet\Calculation\FormulaToken::class, | ||||
|             'PHPExcel_Calculation_Logical' => \PhpOffice\PhpSpreadsheet\Calculation\Logical::class, | ||||
|             'PHPExcel_Calculation_LookupRef' => \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::class, | ||||
|             'PHPExcel_Calculation_MathTrig' => \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::class, | ||||
|             'PHPExcel_Calculation_Statistical' => \PhpOffice\PhpSpreadsheet\Calculation\Statistical::class, | ||||
|             'PHPExcel_Calculation_TextData' => \PhpOffice\PhpSpreadsheet\Calculation\TextData::class, | ||||
|             'PHPExcel_Cell_AdvancedValueBinder' => \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class, | ||||
|             'PHPExcel_Cell_DataType' => \PhpOffice\PhpSpreadsheet\Cell\DataType::class, | ||||
|             'PHPExcel_Cell_DataValidation' => \PhpOffice\PhpSpreadsheet\Cell\DataValidation::class, | ||||
|             'PHPExcel_Cell_DefaultValueBinder' => \PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder::class, | ||||
|             'PHPExcel_Cell_Hyperlink' => \PhpOffice\PhpSpreadsheet\Cell\Hyperlink::class, | ||||
|             'PHPExcel_Cell_IValueBinder' => \PhpOffice\PhpSpreadsheet\Cell\IValueBinder::class, | ||||
|             'PHPExcel_Chart_Axis' => \PhpOffice\PhpSpreadsheet\Chart\Axis::class, | ||||
|             'PHPExcel_Chart_DataSeries' => \PhpOffice\PhpSpreadsheet\Chart\DataSeries::class, | ||||
|             'PHPExcel_Chart_DataSeriesValues' => \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues::class, | ||||
|             'PHPExcel_Chart_Exception' => \PhpOffice\PhpSpreadsheet\Chart\Exception::class, | ||||
|             'PHPExcel_Chart_GridLines' => \PhpOffice\PhpSpreadsheet\Chart\GridLines::class, | ||||
|             'PHPExcel_Chart_Layout' => \PhpOffice\PhpSpreadsheet\Chart\Layout::class, | ||||
|             'PHPExcel_Chart_Legend' => \PhpOffice\PhpSpreadsheet\Chart\Legend::class, | ||||
|             'PHPExcel_Chart_PlotArea' => \PhpOffice\PhpSpreadsheet\Chart\PlotArea::class, | ||||
|             'PHPExcel_Properties' => \PhpOffice\PhpSpreadsheet\Chart\Properties::class, | ||||
|             'PHPExcel_Chart_Title' => \PhpOffice\PhpSpreadsheet\Chart\Title::class, | ||||
|             'PHPExcel_DocumentProperties' => \PhpOffice\PhpSpreadsheet\Document\Properties::class, | ||||
|             'PHPExcel_DocumentSecurity' => \PhpOffice\PhpSpreadsheet\Document\Security::class, | ||||
|             'PHPExcel_Helper_HTML' => \PhpOffice\PhpSpreadsheet\Helper\Html::class, | ||||
|             'PHPExcel_Reader_Abstract' => \PhpOffice\PhpSpreadsheet\Reader\BaseReader::class, | ||||
|             'PHPExcel_Reader_CSV' => \PhpOffice\PhpSpreadsheet\Reader\Csv::class, | ||||
|             'PHPExcel_Reader_DefaultReadFilter' => \PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter::class, | ||||
|             'PHPExcel_Reader_Excel2003XML' => \PhpOffice\PhpSpreadsheet\Reader\Xml::class, | ||||
|             'PHPExcel_Reader_Exception' => \PhpOffice\PhpSpreadsheet\Reader\Exception::class, | ||||
|             'PHPExcel_Reader_Gnumeric' => \PhpOffice\PhpSpreadsheet\Reader\Gnumeric::class, | ||||
|             'PHPExcel_Reader_HTML' => \PhpOffice\PhpSpreadsheet\Reader\Html::class, | ||||
|             'PHPExcel_Reader_IReadFilter' => \PhpOffice\PhpSpreadsheet\Reader\IReadFilter::class, | ||||
|             'PHPExcel_Reader_IReader' => \PhpOffice\PhpSpreadsheet\Reader\IReader::class, | ||||
|             'PHPExcel_Reader_OOCalc' => \PhpOffice\PhpSpreadsheet\Reader\Ods::class, | ||||
|             'PHPExcel_Reader_SYLK' => \PhpOffice\PhpSpreadsheet\Reader\Slk::class, | ||||
|             'PHPExcel_Reader_Excel5' => \PhpOffice\PhpSpreadsheet\Reader\Xls::class, | ||||
|             'PHPExcel_Reader_Excel2007' => \PhpOffice\PhpSpreadsheet\Reader\Xlsx::class, | ||||
|             'PHPExcel_RichText_ITextElement' => \PhpOffice\PhpSpreadsheet\RichText\ITextElement::class, | ||||
|             'PHPExcel_RichText_Run' => \PhpOffice\PhpSpreadsheet\RichText\Run::class, | ||||
|             'PHPExcel_RichText_TextElement' => \PhpOffice\PhpSpreadsheet\RichText\TextElement::class, | ||||
|             'PHPExcel_Shared_CodePage' => \PhpOffice\PhpSpreadsheet\Shared\CodePage::class, | ||||
|             'PHPExcel_Shared_Date' => \PhpOffice\PhpSpreadsheet\Shared\Date::class, | ||||
|             'PHPExcel_Shared_Drawing' => \PhpOffice\PhpSpreadsheet\Shared\Drawing::class, | ||||
|             'PHPExcel_Shared_Escher' => \PhpOffice\PhpSpreadsheet\Shared\Escher::class, | ||||
|             'PHPExcel_Shared_File' => \PhpOffice\PhpSpreadsheet\Shared\File::class, | ||||
|             'PHPExcel_Shared_Font' => \PhpOffice\PhpSpreadsheet\Shared\Font::class, | ||||
|             'PHPExcel_Shared_OLE' => \PhpOffice\PhpSpreadsheet\Shared\OLE::class, | ||||
|             'PHPExcel_Shared_OLERead' => \PhpOffice\PhpSpreadsheet\Shared\OLERead::class, | ||||
|             'PHPExcel_Shared_PasswordHasher' => \PhpOffice\PhpSpreadsheet\Shared\PasswordHasher::class, | ||||
|             'PHPExcel_Shared_String' => \PhpOffice\PhpSpreadsheet\Shared\StringHelper::class, | ||||
|             'PHPExcel_Shared_TimeZone' => \PhpOffice\PhpSpreadsheet\Shared\TimeZone::class, | ||||
|             'PHPExcel_Shared_XMLWriter' => \PhpOffice\PhpSpreadsheet\Shared\XMLWriter::class, | ||||
|             'PHPExcel_Shared_Excel5' => \PhpOffice\PhpSpreadsheet\Shared\Xls::class, | ||||
|             'PHPExcel_Style_Alignment' => \PhpOffice\PhpSpreadsheet\Style\Alignment::class, | ||||
|             'PHPExcel_Style_Border' => \PhpOffice\PhpSpreadsheet\Style\Border::class, | ||||
|             'PHPExcel_Style_Borders' => \PhpOffice\PhpSpreadsheet\Style\Borders::class, | ||||
|             'PHPExcel_Style_Color' => \PhpOffice\PhpSpreadsheet\Style\Color::class, | ||||
|             'PHPExcel_Style_Conditional' => \PhpOffice\PhpSpreadsheet\Style\Conditional::class, | ||||
|             'PHPExcel_Style_Fill' => \PhpOffice\PhpSpreadsheet\Style\Fill::class, | ||||
|             'PHPExcel_Style_Font' => \PhpOffice\PhpSpreadsheet\Style\Font::class, | ||||
|             'PHPExcel_Style_NumberFormat' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::class, | ||||
|             'PHPExcel_Style_Protection' => \PhpOffice\PhpSpreadsheet\Style\Protection::class, | ||||
|             'PHPExcel_Style_Supervisor' => \PhpOffice\PhpSpreadsheet\Style\Supervisor::class, | ||||
|             'PHPExcel_Worksheet_AutoFilter' => \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter::class, | ||||
|             'PHPExcel_Worksheet_BaseDrawing' => \PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing::class, | ||||
|             'PHPExcel_Worksheet_CellIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\CellIterator::class, | ||||
|             'PHPExcel_Worksheet_Column' => \PhpOffice\PhpSpreadsheet\Worksheet\Column::class, | ||||
|             'PHPExcel_Worksheet_ColumnCellIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\ColumnCellIterator::class, | ||||
|             'PHPExcel_Worksheet_ColumnDimension' => \PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension::class, | ||||
|             'PHPExcel_Worksheet_ColumnIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\ColumnIterator::class, | ||||
|             'PHPExcel_Worksheet_Drawing' => \PhpOffice\PhpSpreadsheet\Worksheet\Drawing::class, | ||||
|             'PHPExcel_Worksheet_HeaderFooter' => \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooter::class, | ||||
|             'PHPExcel_Worksheet_HeaderFooterDrawing' => \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing::class, | ||||
|             'PHPExcel_WorksheetIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\Iterator::class, | ||||
|             'PHPExcel_Worksheet_MemoryDrawing' => \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::class, | ||||
|             'PHPExcel_Worksheet_PageMargins' => \PhpOffice\PhpSpreadsheet\Worksheet\PageMargins::class, | ||||
|             'PHPExcel_Worksheet_PageSetup' => \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::class, | ||||
|             'PHPExcel_Worksheet_Protection' => \PhpOffice\PhpSpreadsheet\Worksheet\Protection::class, | ||||
|             'PHPExcel_Worksheet_Row' => \PhpOffice\PhpSpreadsheet\Worksheet\Row::class, | ||||
|             'PHPExcel_Worksheet_RowCellIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\RowCellIterator::class, | ||||
|             'PHPExcel_Worksheet_RowDimension' => \PhpOffice\PhpSpreadsheet\Worksheet\RowDimension::class, | ||||
|             'PHPExcel_Worksheet_RowIterator' => \PhpOffice\PhpSpreadsheet\Worksheet\RowIterator::class, | ||||
|             'PHPExcel_Worksheet_SheetView' => \PhpOffice\PhpSpreadsheet\Worksheet\SheetView::class, | ||||
|             'PHPExcel_Writer_Abstract' => \PhpOffice\PhpSpreadsheet\Writer\BaseWriter::class, | ||||
|             'PHPExcel_Writer_CSV' => \PhpOffice\PhpSpreadsheet\Writer\Csv::class, | ||||
|             'PHPExcel_Writer_Exception' => \PhpOffice\PhpSpreadsheet\Writer\Exception::class, | ||||
|             'PHPExcel_Writer_HTML' => \PhpOffice\PhpSpreadsheet\Writer\Html::class, | ||||
|             'PHPExcel_Writer_IWriter' => \PhpOffice\PhpSpreadsheet\Writer\IWriter::class, | ||||
|             'PHPExcel_Writer_OpenDocument' => \PhpOffice\PhpSpreadsheet\Writer\Ods::class, | ||||
|             'PHPExcel_Writer_PDF' => \PhpOffice\PhpSpreadsheet\Writer\Pdf::class, | ||||
|             'PHPExcel_Writer_Excel5' => \PhpOffice\PhpSpreadsheet\Writer\Xls::class, | ||||
|             'PHPExcel_Writer_Excel2007' => \PhpOffice\PhpSpreadsheet\Writer\Xlsx::class, | ||||
|             'PHPExcel_CachedObjectStorageFactory' => \PhpOffice\PhpSpreadsheet\Collection\CellsFactory::class, | ||||
|             'PHPExcel_Calculation' => \PhpOffice\PhpSpreadsheet\Calculation\Calculation::class, | ||||
|             'PHPExcel_Cell' => \PhpOffice\PhpSpreadsheet\Cell\Cell::class, | ||||
|             'PHPExcel_Chart' => \PhpOffice\PhpSpreadsheet\Chart\Chart::class, | ||||
|             'PHPExcel_Comment' => \PhpOffice\PhpSpreadsheet\Comment::class, | ||||
|             'PHPExcel_Exception' => \PhpOffice\PhpSpreadsheet\Exception::class, | ||||
|             'PHPExcel_HashTable' => \PhpOffice\PhpSpreadsheet\HashTable::class, | ||||
|             'PHPExcel_IComparable' => \PhpOffice\PhpSpreadsheet\IComparable::class, | ||||
|             'PHPExcel_IOFactory' => \PhpOffice\PhpSpreadsheet\IOFactory::class, | ||||
|             'PHPExcel_NamedRange' => \PhpOffice\PhpSpreadsheet\NamedRange::class, | ||||
|             'PHPExcel_ReferenceHelper' => \PhpOffice\PhpSpreadsheet\ReferenceHelper::class, | ||||
|             'PHPExcel_RichText' => \PhpOffice\PhpSpreadsheet\RichText\RichText::class, | ||||
|             'PHPExcel_Settings' => \PhpOffice\PhpSpreadsheet\Settings::class, | ||||
|             'PHPExcel_Style' => \PhpOffice\PhpSpreadsheet\Style\Style::class, | ||||
|             'PHPExcel_Worksheet' => \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::class, | ||||
|         ]; | ||||
| 
 | ||||
|         $methods = [ | ||||
|             'MINUTEOFHOUR' => 'MINUTE', | ||||
|             'SECONDOFMINUTE' => 'SECOND', | ||||
|             'DAYOFWEEK' => 'WEEKDAY', | ||||
|             'WEEKOFYEAR' => 'WEEKNUM', | ||||
|             'ExcelToPHPObject' => 'excelToDateTimeObject', | ||||
|             'ExcelToPHP' => 'excelToTimestamp', | ||||
|             'FormattedPHPToExcel' => 'formattedPHPToExcel', | ||||
|             'Cell::absoluteCoordinate' => 'Coordinate::absoluteCoordinate', | ||||
|             'Cell::absoluteReference' => 'Coordinate::absoluteReference', | ||||
|             'Cell::buildRange' => 'Coordinate::buildRange', | ||||
|             'Cell::columnIndexFromString' => 'Coordinate::columnIndexFromString', | ||||
|             'Cell::coordinateFromString' => 'Coordinate::coordinateFromString', | ||||
|             'Cell::extractAllCellReferencesInRange' => 'Coordinate::extractAllCellReferencesInRange', | ||||
|             'Cell::getRangeBoundaries' => 'Coordinate::getRangeBoundaries', | ||||
|             'Cell::mergeRangesInCollection' => 'Coordinate::mergeRangesInCollection', | ||||
|             'Cell::rangeBoundaries' => 'Coordinate::rangeBoundaries', | ||||
|             'Cell::rangeDimension' => 'Coordinate::rangeDimension', | ||||
|             'Cell::splitRange' => 'Coordinate::splitRange', | ||||
|             'Cell::stringFromColumnIndex' => 'Coordinate::stringFromColumnIndex', | ||||
|         ]; | ||||
| 
 | ||||
|         // Keep '\' prefix for class names
 | ||||
|         $prefixedClasses = []; | ||||
|         foreach ($classes as $key => &$value) { | ||||
|             $value = str_replace('PhpOffice\\', '\\PhpOffice\\', $value); | ||||
|             $prefixedClasses['\\' . $key] = $value; | ||||
|         } | ||||
|         $mapping = $prefixedClasses + $classes + $methods; | ||||
| 
 | ||||
|         return $mapping; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Search in all files in given directory. | ||||
|      * | ||||
|      * @param string $path | ||||
|      */ | ||||
|     private function recursiveReplace($path) | ||||
|     { | ||||
|         $patterns = [ | ||||
|             '/*.md', | ||||
|             '/*.txt', | ||||
|             '/*.TXT', | ||||
|             '/*.php', | ||||
|             '/*.phpt', | ||||
|             '/*.php3', | ||||
|             '/*.php4', | ||||
|             '/*.php5', | ||||
|             '/*.phtml', | ||||
|         ]; | ||||
| 
 | ||||
|         foreach ($patterns as $pattern) { | ||||
|             foreach (glob($path . $pattern) as $file) { | ||||
|                 if (strpos($path, '/vendor/') !== false) { | ||||
|                     echo $file . " skipped\n"; | ||||
| 
 | ||||
|                     continue; | ||||
|                 } | ||||
|                 $original = file_get_contents($file); | ||||
|                 $converted = $this->replace($original); | ||||
| 
 | ||||
|                 if ($original !== $converted) { | ||||
|                     echo $file . " converted\n"; | ||||
|                     file_put_contents($file, $converted); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Do the recursion in subdirectory
 | ||||
|         foreach (glob($path . '/*', GLOB_ONLYDIR) as $subpath) { | ||||
|             if (strpos($subpath, $path . '/') === 0) { | ||||
|                 $this->recursiveReplace($subpath); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function migrate() | ||||
|     { | ||||
|         $path = realpath(getcwd()); | ||||
|         echo 'This will search and replace recursively in ' . $path . PHP_EOL; | ||||
|         echo 'You MUST backup your files first, or you risk losing data.' . PHP_EOL; | ||||
|         echo 'Are you sure ? (y/n)'; | ||||
| 
 | ||||
|         $confirm = fread(STDIN, 1); | ||||
|         if ($confirm === 'y') { | ||||
|             $this->recursiveReplace($path); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Migrate the given code from PHPExcel to PhpSpreadsheet. | ||||
|      * | ||||
|      * @param string $original | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function replace($original) | ||||
|     { | ||||
|         $converted = str_replace($this->from, $this->to, $original); | ||||
| 
 | ||||
|         // The string "PHPExcel" gets special treatment because of how common it might be.
 | ||||
|         // This regex requires a word boundary around the string, and it can't be
 | ||||
|         // preceded by $ or -> (goal is to filter out cases where a variable is named $PHPExcel or similar)
 | ||||
|         $converted = preg_replace('~(?<!\$|->)(\b|\\\\)PHPExcel\b~', '\\' . \PhpOffice\PhpSpreadsheet\Spreadsheet::class, $converted); | ||||
| 
 | ||||
|         return $converted; | ||||
|     } | ||||
| } | ||||
| @ -11,6 +11,7 @@ use RecursiveIteratorIterator; | ||||
| use RecursiveRegexIterator; | ||||
| use ReflectionClass; | ||||
| use RegexIterator; | ||||
| use RuntimeException; | ||||
| 
 | ||||
| /** | ||||
|  * Helper class to be used in sample code. | ||||
| @ -106,11 +107,10 @@ class Sample | ||||
|     /** | ||||
|      * Write documents. | ||||
|      * | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * @param string $filename | ||||
|      * @param string[] $writers | ||||
|      */ | ||||
|     public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']) | ||||
|     public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xlsx', 'Xls']): void | ||||
|     { | ||||
|         // Set active sheet index to the first sheet, so Excel opens this as the first sheet
 | ||||
|         $spreadsheet->setActiveSheetIndex(0); | ||||
| @ -142,7 +142,7 @@ class Sample | ||||
|         $tempFolder = sys_get_temp_dir() . '/phpspreadsheet'; | ||||
|         if (!is_dir($tempFolder)) { | ||||
|             if (!mkdir($tempFolder) && !is_dir($tempFolder)) { | ||||
|                 throw new \RuntimeException(sprintf('Directory "%s" was not created', $tempFolder)); | ||||
|                 throw new RuntimeException(sprintf('Directory "%s" was not created', $tempFolder)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -179,7 +179,7 @@ class Sample | ||||
|         return $temporaryFilename . '.' . $extension; | ||||
|     } | ||||
| 
 | ||||
|     public function log($message) | ||||
|     public function log($message): void | ||||
|     { | ||||
|         $eol = $this->isCli() ? PHP_EOL : '<br />'; | ||||
|         echo date('H:i:s ') . $message . $eol; | ||||
| @ -188,7 +188,7 @@ class Sample | ||||
|     /** | ||||
|      * Log ending notes. | ||||
|      */ | ||||
|     public function logEndingNotes() | ||||
|     public function logEndingNotes(): void | ||||
|     { | ||||
|         // Do not show execution time for index
 | ||||
|         $this->log('Peak memory usage: ' . (memory_get_peak_usage(true) / 1024 / 1024) . 'MB'); | ||||
| @ -197,11 +197,10 @@ class Sample | ||||
|     /** | ||||
|      * Log a line about the write operation. | ||||
|      * | ||||
|      * @param IWriter $writer | ||||
|      * @param string $path | ||||
|      * @param float $callStartTime | ||||
|      */ | ||||
|     public function logWrite(IWriter $writer, $path, $callStartTime) | ||||
|     public function logWrite(IWriter $writer, $path, $callStartTime): void | ||||
|     { | ||||
|         $callEndTime = microtime(true); | ||||
|         $callTime = $callEndTime - $callStartTime; | ||||
| @ -219,7 +218,7 @@ class Sample | ||||
|      * @param string $path | ||||
|      * @param float $callStartTime | ||||
|      */ | ||||
|     public function logRead($format, $path, $callStartTime) | ||||
|     public function logRead($format, $path, $callStartTime): void | ||||
|     { | ||||
|         $callEndTime = microtime(true); | ||||
|         $callTime = $callEndTime - $callStartTime; | ||||
|  | ||||
| @ -37,11 +37,8 @@ abstract class IOFactory | ||||
|     /** | ||||
|      * Create Writer\IWriter. | ||||
|      * | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * @param string $writerType Example: Xlsx | ||||
|      * | ||||
|      * @throws Writer\Exception | ||||
|      * | ||||
|      * @return Writer\IWriter | ||||
|      */ | ||||
|     public static function createWriter(Spreadsheet $spreadsheet, $writerType) | ||||
| @ -61,8 +58,6 @@ abstract class IOFactory | ||||
|      * | ||||
|      * @param string $readerType Example: Xlsx | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return Reader\IReader | ||||
|      */ | ||||
|     public static function createReader($readerType) | ||||
| @ -82,8 +77,6 @@ abstract class IOFactory | ||||
|      * | ||||
|      * @param string $pFilename The name of the spreadsheet file | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public static function load($pFilename) | ||||
| @ -98,8 +91,6 @@ abstract class IOFactory | ||||
|      * | ||||
|      * @param string $pFilename The name of the spreadsheet file to identify | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public static function identify($pFilename) | ||||
| @ -117,8 +108,6 @@ abstract class IOFactory | ||||
|      * | ||||
|      * @param string $filename The name of the spreadsheet file | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return Reader\IReader | ||||
|      */ | ||||
|     public static function createReaderForFile($filename) | ||||
| @ -202,7 +191,7 @@ abstract class IOFactory | ||||
|      * @param string $writerType | ||||
|      * @param string $writerClass | ||||
|      */ | ||||
|     public static function registerWriter($writerType, $writerClass) | ||||
|     public static function registerWriter($writerType, $writerClass): void | ||||
|     { | ||||
|         if (!is_a($writerClass, Writer\IWriter::class, true)) { | ||||
|             throw new Writer\Exception('Registered writers must implement ' . Writer\IWriter::class); | ||||
| @ -217,7 +206,7 @@ abstract class IOFactory | ||||
|      * @param string $readerType | ||||
|      * @param string $readerClass | ||||
|      */ | ||||
|     public static function registerReader($readerType, $readerClass) | ||||
|     public static function registerReader($readerType, $readerClass): void | ||||
|     { | ||||
|         if (!is_a($readerClass, Reader\IReader::class, true)) { | ||||
|             throw new Reader\Exception('Registered readers must implement ' . Reader\IReader::class); | ||||
|  | ||||
| @ -45,12 +45,9 @@ class NamedRange | ||||
|      * Create a new NamedRange. | ||||
|      * | ||||
|      * @param string $pName | ||||
|      * @param Worksheet $pWorksheet | ||||
|      * @param string $pRange | ||||
|      * @param bool $pLocalOnly | ||||
|      * @param null|Worksheet $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function __construct($pName, Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) | ||||
|     { | ||||
| @ -125,7 +122,7 @@ class NamedRange | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setWorksheet(Worksheet $value = null) | ||||
|     public function setWorksheet(?Worksheet $value = null) | ||||
|     { | ||||
|         if ($value !== null) { | ||||
|             $this->worksheet = $value; | ||||
| @ -198,11 +195,9 @@ class NamedRange | ||||
|     /** | ||||
|      * Set scope. | ||||
|      * | ||||
|      * @param null|Worksheet $value | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function setScope(Worksheet $value = null) | ||||
|     public function setScope(?Worksheet $value = null) | ||||
|     { | ||||
|         $this->scope = $value; | ||||
|         $this->localOnly = $value != null; | ||||
|  | ||||
| @ -144,15 +144,13 @@ abstract class BaseReader implements IReader | ||||
|      * Open file for reading. | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     protected function openFile($pFilename) | ||||
|     protected function openFile($pFilename): void | ||||
|     { | ||||
|         File::assertFile($pFilename); | ||||
| 
 | ||||
|         // Open file
 | ||||
|         $this->fileHandle = fopen($pFilename, 'r'); | ||||
|         $this->fileHandle = fopen($pFilename, 'rb'); | ||||
|         if ($this->fileHandle === false) { | ||||
|             throw new Exception('Could not open file ' . $pFilename . ' for reading.'); | ||||
|         } | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| namespace PhpOffice\PhpSpreadsheet\Reader; | ||||
| 
 | ||||
| use InvalidArgumentException; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\Coordinate; | ||||
| use PhpOffice\PhpSpreadsheet\Shared\StringHelper; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| @ -43,13 +44,6 @@ class Csv extends BaseReader | ||||
|      */ | ||||
|     private $contiguous = false; | ||||
| 
 | ||||
|     /** | ||||
|      * Row counter for loading rows contiguously. | ||||
|      * | ||||
|      * @var int | ||||
|      */ | ||||
|     private $contiguousRow = -1; | ||||
| 
 | ||||
|     /** | ||||
|      * The character that can escape the enclosure. | ||||
|      * | ||||
| @ -92,7 +86,7 @@ class Csv extends BaseReader | ||||
|     /** | ||||
|      * Move filepointer past any BOM marker. | ||||
|      */ | ||||
|     protected function skipBOM() | ||||
|     protected function skipBOM(): void | ||||
|     { | ||||
|         rewind($this->fileHandle); | ||||
| 
 | ||||
| @ -101,28 +95,6 @@ class Csv extends BaseReader | ||||
|                 fgets($this->fileHandle, 4) == "\xEF\xBB\xBF" ? | ||||
|                     fseek($this->fileHandle, 3) : fseek($this->fileHandle, 0); | ||||
| 
 | ||||
|                 break; | ||||
|             case 'UTF-16LE': | ||||
|                 fgets($this->fileHandle, 3) == "\xFF\xFE" ? | ||||
|                     fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); | ||||
| 
 | ||||
|                 break; | ||||
|             case 'UTF-16BE': | ||||
|                 fgets($this->fileHandle, 3) == "\xFE\xFF" ? | ||||
|                     fseek($this->fileHandle, 2) : fseek($this->fileHandle, 0); | ||||
| 
 | ||||
|                 break; | ||||
|             case 'UTF-32LE': | ||||
|                 fgets($this->fileHandle, 5) == "\xFF\xFE\x00\x00" ? | ||||
|                     fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); | ||||
| 
 | ||||
|                 break; | ||||
|             case 'UTF-32BE': | ||||
|                 fgets($this->fileHandle, 5) == "\x00\x00\xFE\xFF" ? | ||||
|                     fseek($this->fileHandle, 4) : fseek($this->fileHandle, 0); | ||||
| 
 | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| @ -130,7 +102,7 @@ class Csv extends BaseReader | ||||
|     /** | ||||
|      * Identify any separator that is explicitly set in the file. | ||||
|      */ | ||||
|     protected function checkSeparator() | ||||
|     protected function checkSeparator(): void | ||||
|     { | ||||
|         $line = fgets($this->fileHandle); | ||||
|         if ($line === false) { | ||||
| @ -149,7 +121,7 @@ class Csv extends BaseReader | ||||
|     /** | ||||
|      * Infer the separator if it isn't explicitly set in the file or specified by the user. | ||||
|      */ | ||||
|     protected function inferSeparator() | ||||
|     protected function inferSeparator(): void | ||||
|     { | ||||
|         if ($this->delimiter !== null) { | ||||
|             return; | ||||
| @ -207,7 +179,7 @@ class Csv extends BaseReader | ||||
|             $meanSquareDeviations[$delimiter] = array_reduce( | ||||
|                 $series, | ||||
|                 function ($sum, $value) use ($median) { | ||||
|                     return $sum + pow($value - $median, 2); | ||||
|                     return $sum + ($value - $median) ** 2; | ||||
|                 } | ||||
|             ) / count($series); | ||||
|         } | ||||
| @ -236,33 +208,31 @@ class Csv extends BaseReader | ||||
|     /** | ||||
|      * Get the next full line from the file. | ||||
|      * | ||||
|      * @param string $line | ||||
|      * | ||||
|      * @return bool|string | ||||
|      * @return false|string | ||||
|      */ | ||||
|     private function getNextLine($line = '') | ||||
|     private function getNextLine() | ||||
|     { | ||||
|         // Get the next line in the file
 | ||||
|         $newLine = fgets($this->fileHandle); | ||||
|         $line = ''; | ||||
|         $enclosure = '(?<!' . preg_quote($this->escapeCharacter, '/') . ')' . preg_quote($this->enclosure, '/'); | ||||
| 
 | ||||
|         // Return false if there is no next line
 | ||||
|         if ($newLine === false) { | ||||
|             return false; | ||||
|         } | ||||
|         do { | ||||
|             // Get the next line in the file
 | ||||
|             $newLine = fgets($this->fileHandle); | ||||
| 
 | ||||
|         // Add the new line to the line passed in
 | ||||
|         $line = $line . $newLine; | ||||
|             // Return false if there is no next line
 | ||||
|             if ($newLine === false) { | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|         // Drop everything that is enclosed to avoid counting false positives in enclosures
 | ||||
|         $enclosure = '(?<!' . preg_quote($this->escapeCharacter, '/') . ')' | ||||
|             . preg_quote($this->enclosure, '/'); | ||||
|         $line = preg_replace('/(' . $enclosure . '.*' . $enclosure . ')/Us', '', $line); | ||||
|             // Add the new line to the line passed in
 | ||||
|             $line = $line . $newLine; | ||||
| 
 | ||||
|         // See if we have any enclosures left in the line
 | ||||
|         // if we still have an enclosure then we need to read the next line as well
 | ||||
|         if (preg_match('/(' . $enclosure . ')/', $line) > 0) { | ||||
|             $line = $this->getNextLine($line); | ||||
|         } | ||||
|             // Drop everything that is enclosed to avoid counting false positives in enclosures
 | ||||
|             $line = preg_replace('/(' . $enclosure . '.*' . $enclosure . ')/Us', '', $line); | ||||
| 
 | ||||
|             // See if we have any enclosures left in the line
 | ||||
|             // if we still have an enclosure then we need to read the next line as well
 | ||||
|         } while (preg_match('/(' . $enclosure . ')/', $line) > 0); | ||||
| 
 | ||||
|         return $line; | ||||
|     } | ||||
| @ -272,17 +242,12 @@ class Csv extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listWorksheetInfo($pFilename) | ||||
|     { | ||||
|         // Open file
 | ||||
|         if (!$this->canRead($pFilename)) { | ||||
|             throw new Exception($pFilename . ' is an Invalid Spreadsheet file.'); | ||||
|         } | ||||
|         $this->openFile($pFilename); | ||||
|         $this->openFileOrMemory($pFilename); | ||||
|         $fileHandle = $this->fileHandle; | ||||
| 
 | ||||
|         // Skip BOM, if any
 | ||||
| @ -317,8 +282,6 @@ class Csv extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public function load($pFilename) | ||||
| @ -330,13 +293,28 @@ class Csv extends BaseReader | ||||
|         return $this->loadIntoExisting($pFilename, $spreadsheet); | ||||
|     } | ||||
| 
 | ||||
|     private function openFileOrMemory($pFilename): void | ||||
|     { | ||||
|         // Open file
 | ||||
|         $fhandle = $this->canRead($pFilename); | ||||
|         if (!$fhandle) { | ||||
|             throw new Exception($pFilename . ' is an Invalid Spreadsheet file.'); | ||||
|         } | ||||
|         $this->openFile($pFilename); | ||||
|         if ($this->inputEncoding !== 'UTF-8') { | ||||
|             fclose($this->fileHandle); | ||||
|             $entireFile = file_get_contents($pFilename); | ||||
|             $this->fileHandle = fopen('php://memory', 'r+b'); | ||||
|             $data = StringHelper::convertEncoding($entireFile, 'UTF-8', $this->inputEncoding); | ||||
|             fwrite($this->fileHandle, $data); | ||||
|             rewind($this->fileHandle); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
| @ -346,10 +324,7 @@ class Csv extends BaseReader | ||||
|         ini_set('auto_detect_line_endings', true); | ||||
| 
 | ||||
|         // Open file
 | ||||
|         if (!$this->canRead($pFilename)) { | ||||
|             throw new Exception($pFilename . ' is an Invalid Spreadsheet file.'); | ||||
|         } | ||||
|         $this->openFile($pFilename); | ||||
|         $this->openFileOrMemory($pFilename); | ||||
|         $fileHandle = $this->fileHandle; | ||||
| 
 | ||||
|         // Skip BOM, if any
 | ||||
| @ -365,22 +340,24 @@ class Csv extends BaseReader | ||||
| 
 | ||||
|         // Set our starting row based on whether we're in contiguous mode or not
 | ||||
|         $currentRow = 1; | ||||
|         if ($this->contiguous) { | ||||
|             $currentRow = ($this->contiguousRow == -1) ? $sheet->getHighestRow() : $this->contiguousRow; | ||||
|         } | ||||
|         $outRow = 0; | ||||
| 
 | ||||
|         // Loop through each line of the file in turn
 | ||||
|         while (($rowData = fgetcsv($fileHandle, 0, $this->delimiter, $this->enclosure, $this->escapeCharacter)) !== false) { | ||||
|             $noOutputYet = true; | ||||
|             $columnLetter = 'A'; | ||||
|             foreach ($rowData as $rowDatum) { | ||||
|                 if ($rowDatum != '' && $this->readFilter->readCell($columnLetter, $currentRow)) { | ||||
|                     // Convert encoding if necessary
 | ||||
|                     if ($this->inputEncoding !== 'UTF-8') { | ||||
|                         $rowDatum = StringHelper::convertEncoding($rowDatum, 'UTF-8', $this->inputEncoding); | ||||
|                     if ($this->contiguous) { | ||||
|                         if ($noOutputYet) { | ||||
|                             $noOutputYet = false; | ||||
|                             ++$outRow; | ||||
|                         } | ||||
|                     } else { | ||||
|                         $outRow = $currentRow; | ||||
|                     } | ||||
| 
 | ||||
|                     // Set cell value
 | ||||
|                     $sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); | ||||
|                     $sheet->getCell($columnLetter . $outRow)->setValue($rowDatum); | ||||
|                 } | ||||
|                 ++$columnLetter; | ||||
|             } | ||||
| @ -390,10 +367,6 @@ class Csv extends BaseReader | ||||
|         // Close file
 | ||||
|         fclose($fileHandle); | ||||
| 
 | ||||
|         if ($this->contiguous) { | ||||
|             $this->contiguousRow = $currentRow; | ||||
|         } | ||||
| 
 | ||||
|         ini_set('auto_detect_line_endings', $lineEnding); | ||||
| 
 | ||||
|         // Return
 | ||||
| @ -485,9 +458,6 @@ class Csv extends BaseReader | ||||
|     public function setContiguous($contiguous) | ||||
|     { | ||||
|         $this->contiguous = (bool) $contiguous; | ||||
|         if (!$contiguous) { | ||||
|             $this->contiguousRow = -1; | ||||
|         } | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @ -538,7 +508,7 @@ class Csv extends BaseReader | ||||
|         // Check if file exists
 | ||||
|         try { | ||||
|             $this->openFile($pFilename); | ||||
|         } catch (Exception $e) { | ||||
|         } catch (InvalidArgumentException $e) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -46,8 +46,6 @@ class Gnumeric extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function canRead($pFilename) | ||||
| @ -60,7 +58,7 @@ class Gnumeric extends BaseReader | ||||
|         } | ||||
| 
 | ||||
|         // Read signature data (first 3 bytes)
 | ||||
|         $fh = fopen($pFilename, 'r'); | ||||
|         $fh = fopen($pFilename, 'rb'); | ||||
|         $data = fread($fh, 2); | ||||
|         fclose($fh); | ||||
| 
 | ||||
| @ -169,8 +167,6 @@ class Gnumeric extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public function load($pFilename) | ||||
| @ -186,9 +182,6 @@ class Gnumeric extends BaseReader | ||||
|      * Loads from file into Spreadsheet instance. | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
| @ -479,7 +472,7 @@ class Gnumeric extends BaseReader | ||||
|                     $endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol']; | ||||
|                     $endColumn = Coordinate::stringFromColumnIndex($endColumn + 1); | ||||
|                     $endRow = ($styleAttributes['endRow'] > $maxRow) ? $maxRow : $styleAttributes['endRow']; | ||||
|                     $endRow += 1; | ||||
|                     ++$endRow; | ||||
|                     $cellRange = $startColumn . $startRow . ':' . $endColumn . $endRow; | ||||
| 
 | ||||
|                     $styleAttributes = $styleRegion->Style->attributes(); | ||||
|  | ||||
| @ -205,8 +205,6 @@ class Html extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public function load($pFilename) | ||||
| @ -272,7 +270,7 @@ class Html extends BaseReader | ||||
|         return array_pop($this->nestedColumn); | ||||
|     } | ||||
| 
 | ||||
|     protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent) | ||||
|     protected function flushCell(Worksheet $sheet, $column, $row, &$cellContent): void | ||||
|     { | ||||
|         if (is_string($cellContent)) { | ||||
|             //    Simple String content
 | ||||
| @ -292,13 +290,11 @@ class Html extends BaseReader | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param DOMNode $element | ||||
|      * @param Worksheet $sheet | ||||
|      * @param int $row | ||||
|      * @param string $column | ||||
|      * @param string $cellContent | ||||
|      */ | ||||
|     protected function processDomElement(DOMNode $element, Worksheet $sheet, &$row, &$column, &$cellContent) | ||||
|     protected function processDomElement(DOMNode $element, Worksheet $sheet, &$row, &$column, &$cellContent): void | ||||
|     { | ||||
|         foreach ($element->childNodes as $child) { | ||||
|             if ($child instanceof DOMText) { | ||||
| @ -579,9 +575,6 @@ class Html extends BaseReader | ||||
|      * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
| @ -607,9 +600,6 @@ class Html extends BaseReader | ||||
|      * Spreadsheet from content. | ||||
|      * | ||||
|      * @param string $content | ||||
|      * @param null|Spreadsheet $spreadsheet | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public function loadFromString($content, ?Spreadsheet $spreadsheet = null): Spreadsheet | ||||
|     { | ||||
| @ -626,13 +616,6 @@ class Html extends BaseReader | ||||
| 
 | ||||
|     /** | ||||
|      * 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 | ||||
|     { | ||||
| @ -693,7 +676,7 @@ class Html extends BaseReader | ||||
|      * @param string $column | ||||
|      * @param array $attributeArray | ||||
|      */ | ||||
|     private function applyInlineStyle(&$sheet, $row, $column, $attributeArray) | ||||
|     private function applyInlineStyle(&$sheet, $row, $column, $attributeArray): void | ||||
|     { | ||||
|         if (!isset($attributeArray['style'])) { | ||||
|             return; | ||||
| @ -858,14 +841,10 @@ class Html extends BaseReader | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param Worksheet $sheet | ||||
|      * @param string    $column | ||||
|      * @param int       $row | ||||
|      * @param array     $attributes | ||||
|      * | ||||
|      * @throws \PhpOffice\PhpSpreadsheet\Exception | ||||
|      */ | ||||
|     private function insertImage(Worksheet $sheet, $column, $row, array $attributes) | ||||
|     private function insertImage(Worksheet $sheet, $column, $row, array $attributes): void | ||||
|     { | ||||
|         if (!isset($attributes['src'])) { | ||||
|             return; | ||||
| @ -949,11 +928,10 @@ class Html extends BaseReader | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param Style  $cellStyle | ||||
|      * @param string $styleValue | ||||
|      * @param string $type | ||||
|      */ | ||||
|     private function setBorderStyle(Style $cellStyle, $styleValue, $type) | ||||
|     private function setBorderStyle(Style $cellStyle, $styleValue, $type): void | ||||
|     { | ||||
|         [, $borderStyle, $color] = explode(' ', $styleValue); | ||||
| 
 | ||||
|  | ||||
| @ -118,8 +118,6 @@ interface IReader | ||||
|     /** | ||||
|      * Set read filter. | ||||
|      * | ||||
|      * @param IReadFilter $pValue | ||||
|      * | ||||
|      * @return IReader | ||||
|      */ | ||||
|     public function setReadFilter(IReadFilter $pValue); | ||||
| @ -129,8 +127,6 @@ interface IReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return \PhpOffice\PhpSpreadsheet\Spreadsheet | ||||
|      */ | ||||
|     public function load($pFilename); | ||||
|  | ||||
| @ -4,6 +4,10 @@ namespace PhpOffice\PhpSpreadsheet\Reader; | ||||
| 
 | ||||
| use DateTime; | ||||
| use DateTimeZone; | ||||
| use DOMAttr; | ||||
| use DOMDocument; | ||||
| use DOMElement; | ||||
| use DOMNode; | ||||
| use PhpOffice\PhpSpreadsheet\Calculation\Calculation; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\Coordinate; | ||||
| use PhpOffice\PhpSpreadsheet\Cell\DataType; | ||||
| @ -34,8 +38,6 @@ class Ods extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function canRead($pFilename) | ||||
| @ -85,8 +87,6 @@ class Ods extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function listWorksheetNames($pFilename) | ||||
| @ -139,8 +139,6 @@ class Ods extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listWorksheetInfo($pFilename) | ||||
| @ -233,8 +231,6 @@ class Ods extends BaseReader | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
|     public function load($pFilename) | ||||
| @ -250,9 +246,6 @@ class Ods extends BaseReader | ||||
|      * Loads PhpSpreadsheet from file into PhpSpreadsheet instance. | ||||
|      * | ||||
|      * @param string $pFilename | ||||
|      * @param Spreadsheet $spreadsheet | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * | ||||
|      * @return Spreadsheet | ||||
|      */ | ||||
| @ -261,7 +254,7 @@ class Ods extends BaseReader | ||||
|         File::assertFile($pFilename); | ||||
| 
 | ||||
|         $timezoneObj = new DateTimeZone('Europe/London'); | ||||
|         $GMT = new \DateTimeZone('UTC'); | ||||
|         $GMT = new DateTimeZone('UTC'); | ||||
| 
 | ||||
|         $zip = new ZipArchive(); | ||||
|         if (!$zip->open($pFilename)) { | ||||
| @ -285,7 +278,7 @@ class Ods extends BaseReader | ||||
| 
 | ||||
|         // Content
 | ||||
| 
 | ||||
|         $dom = new \DOMDocument('1.01', 'UTF-8'); | ||||
|         $dom = new DOMDocument('1.01', 'UTF-8'); | ||||
|         $dom->loadXML( | ||||
|             $this->securityScanner->scan($zip->getFromName('content.xml')), | ||||
|             Settings::getLibXmlLoaderOptions() | ||||
| @ -301,12 +294,12 @@ class Ods extends BaseReader | ||||
|             ->getElementsByTagNameNS($officeNs, 'spreadsheet'); | ||||
| 
 | ||||
|         foreach ($spreadsheets as $workbookData) { | ||||
|             /** @var \DOMElement $workbookData */ | ||||
|             /** @var DOMElement $workbookData */ | ||||
|             $tables = $workbookData->getElementsByTagNameNS($tableNs, 'table'); | ||||
| 
 | ||||
|             $worksheetID = 0; | ||||
|             foreach ($tables as $worksheetDataSet) { | ||||
|                 /** @var \DOMElement $worksheetDataSet */ | ||||
|                 /** @var DOMElement $worksheetDataSet */ | ||||
|                 $worksheetName = $worksheetDataSet->getAttributeNS($tableNs, 'name'); | ||||
| 
 | ||||
|                 // Check loadSheetsOnly
 | ||||
| @ -332,7 +325,7 @@ class Ods extends BaseReader | ||||
|                 // Go through every child of table element
 | ||||
|                 $rowID = 1; | ||||
|                 foreach ($worksheetDataSet->childNodes as $childNode) { | ||||
|                     /** @var \DOMElement $childNode */ | ||||
|                     /** @var DOMElement $childNode */ | ||||
| 
 | ||||
|                     // Filter elements which are not under the "table" ns
 | ||||
|                     if ($childNode->namespaceURI != $tableNs) { | ||||
| @ -405,11 +398,11 @@ class Ods extends BaseReader | ||||
| 
 | ||||
|                                 // Content
 | ||||
| 
 | ||||
|                                 /** @var \DOMElement[] $paragraphs */ | ||||
|                                 /** @var DOMElement[] $paragraphs */ | ||||
|                                 $paragraphs = []; | ||||
| 
 | ||||
|                                 foreach ($cellData->childNodes as $item) { | ||||
|                                     /** @var \DOMElement $item */ | ||||
|                                     /** @var DOMElement $item */ | ||||
| 
 | ||||
|                                     // Filter text:p elements
 | ||||
|                                     if ($item->nodeName == 'text:p') { | ||||
| @ -659,22 +652,20 @@ class Ods extends BaseReader | ||||
|     /** | ||||
|      * Recursively scan element. | ||||
|      * | ||||
|      * @param \DOMNode $element | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function scanElementForText(\DOMNode $element) | ||||
|     protected function scanElementForText(DOMNode $element) | ||||
|     { | ||||
|         $str = ''; | ||||
|         foreach ($element->childNodes as $child) { | ||||
|             /** @var \DOMNode $child */ | ||||
|             /** @var DOMNode $child */ | ||||
|             if ($child->nodeType == XML_TEXT_NODE) { | ||||
|                 $str .= $child->nodeValue; | ||||
|             } elseif ($child->nodeType == XML_ELEMENT_NODE && $child->nodeName == 'text:s') { | ||||
|                 // It's a space
 | ||||
| 
 | ||||
|                 // Multiple spaces?
 | ||||
|                 /** @var \DOMAttr $cAttr */ | ||||
|                 /** @var DOMAttr $cAttr */ | ||||
|                 $cAttr = $child->attributes->getNamedItem('c'); | ||||
|                 if ($cAttr) { | ||||
|                     $multiplier = (int) $cAttr->nodeValue; | ||||
|  | ||||
| @ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Reader\Ods; | ||||
| 
 | ||||
| use PhpOffice\PhpSpreadsheet\Document\Properties as DocumentProperties; | ||||
| use PhpOffice\PhpSpreadsheet\Spreadsheet; | ||||
| use SimpleXMLElement; | ||||
| 
 | ||||
| class Properties | ||||
| { | ||||
| @ -14,7 +15,7 @@ class Properties | ||||
|         $this->spreadsheet = $spreadsheet; | ||||
|     } | ||||
| 
 | ||||
|     public function load(\SimpleXMLElement $xml, $namespacesMeta) | ||||
|     public function load(SimpleXMLElement $xml, $namespacesMeta): void | ||||
|     { | ||||
|         $docProps = $this->spreadsheet->getProperties(); | ||||
|         $officeProperty = $xml->children($namespacesMeta['office']); | ||||
| @ -35,7 +36,7 @@ class Properties | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function setCoreProperties(DocumentProperties $docProps, \SimpleXMLElement $officePropertyDC) | ||||
|     private function setCoreProperties(DocumentProperties $docProps, SimpleXMLElement $officePropertyDC): void | ||||
|     { | ||||
|         foreach ($officePropertyDC as $propertyName => $propertyValue) { | ||||
|             $propertyValue = (string) $propertyValue; | ||||
| @ -73,10 +74,10 @@ class Properties | ||||
| 
 | ||||
|     private function setMetaProperties( | ||||
|         $namespacesMeta, | ||||
|         \SimpleXMLElement $propertyValue, | ||||
|         SimpleXMLElement $propertyValue, | ||||
|         $propertyName, | ||||
|         DocumentProperties $docProps | ||||
|     ) { | ||||
|     ): void { | ||||
|         $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); | ||||
|         $propertyValue = (string) $propertyValue; | ||||
|         switch ($propertyName) { | ||||
| @ -100,7 +101,7 @@ class Properties | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function setUserDefinedProperty($propertyValueAttributes, $propertyValue, DocumentProperties $docProps) | ||||
|     private function setUserDefinedProperty($propertyValueAttributes, $propertyValue, DocumentProperties $docProps): void | ||||
|     { | ||||
|         $propertyValueName = ''; | ||||
|         $propertyValueType = DocumentProperties::PROPERTY_TYPE_STRING; | ||||
|  | ||||
| @ -61,7 +61,7 @@ class XmlScanner | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     private function disableEntityLoaderCheck() | ||||
|     private function disableEntityLoaderCheck(): void | ||||
|     { | ||||
|         if (Settings::getLibXmlDisableEntityLoader()) { | ||||
|             $libxmlDisableEntityLoaderValue = libxml_disable_entity_loader(true); | ||||
| @ -72,7 +72,7 @@ class XmlScanner | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static function shutdown() | ||||
|     public static function shutdown(): void | ||||
|     { | ||||
|         if (self::$libxmlDisableEntityLoaderValue !== null) { | ||||
|             libxml_disable_entity_loader(self::$libxmlDisableEntityLoaderValue); | ||||
| @ -85,7 +85,7 @@ class XmlScanner | ||||
|         self::shutdown(); | ||||
|     } | ||||
| 
 | ||||
|     public function setAdditionalCallback(callable $callback) | ||||
|     public function setAdditionalCallback(callable $callback): void | ||||
|     { | ||||
|         $this->callback = $callback; | ||||
|     } | ||||
| @ -114,8 +114,6 @@ class XmlScanner | ||||
|      * | ||||
|      * @param mixed $xml | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function scan($xml) | ||||
| @ -143,8 +141,6 @@ class XmlScanner | ||||
|      * | ||||
|      * @param string $filestream | ||||
|      * | ||||
|      * @throws Reader\Exception | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function scanFile($filestream) | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user
	 oleibman
						oleibman