diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index a7c44ddb19..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -charset = utf-8 -indent_size = 4 -indent_style = space -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -trim_trailing_whitespace = false - -[*.{yml,yaml}] -indent_size = 2 diff --git a/.gitattributes b/.gitattributes index b70296d120..0042fb0f6f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,20 +1,3 @@ -*.min.js binary -/.editorconfig export-ignore -/.gitattributes export-ignore -/.github export-ignore -/.gitignore export-ignore -/.php-cs-fixer.dist.php export-ignore -/.phpcs.xml.dist export-ignore -/.readthedocs.yaml export-ignore -/.scrutinizer.yml export-ignore -/CHANGELOG.PHPExcel.md export-ignore -/bin export-ignore -/composer.lock export-ignore -/docs export-ignore -/infra export-ignore -/mkdocs.yml export-ignore -/phpstan-baseline.neon export-ignore -/phpstan.neon.dist export-ignore -/phpunit.xml.dist export-ignore -/samples export-ignore /tests export-ignore +README.md export-ignore +*.min.js binary diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index e2e66a4a07..c25612aa51 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,7 +14,7 @@ This is: ### What are the steps to reproduce? -Please provide a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) of code that exhibits the issue without relying on an external Excel file or a web server: +Please provide a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) of code that exhibits the issue without relying on an external Excel file or a web server: ```php This looks like a support question. Please ask your support questions on - [StackOverflow](https://stackoverflow.com/questions/tagged/phpspreadsheet), + [StackOverflow](http://stackoverflow.com/questions/tagged/phpspreadsheet), or [Gitter](https://gitter.im/PHPOffice/PhpSpreadsheet). Thank you for your contributions. diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml deleted file mode 100644 index 0280cc7b76..0000000000 --- a/.github/workflows/github-pages.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: GithHub Pages -on: - push: - tags: - - '*' - -permissions: {} -jobs: - github-pages: - permissions: - contents: write # to push pages branch (peaceiris/actions-gh-pages) - - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - coverage: none # remove xdebug - - - name: Build API documentation - run: | - curl -LO https://github.com/phpDocumentor/phpDocumentor/releases/download/v3.5.0/phpDocumentor.phar - php phpDocumentor.phar --directory src/ --target docs/api - - - name: Deploy to GithHub Pages - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/api diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index cf6e82687f..0000000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,274 +0,0 @@ -name: main -on: [ push, pull_request, merge_group ] -permissions: - contents: read # to fetch code (actions/checkout) -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - experimental: - - false - php-version: - - '8.1' - - '8.2' - - '8.3' - - '8.4' - - include: - - php-version: 'nightly' - experimental: true - - name: PHP ${{ matrix.php-version }} - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install locales - run: sudo apt-get update && sudo apt-get install -y language-pack-fr language-pack-de - - - name: Install single-byte locale - run: sudo sed -i -e 's/# de_DE@euro/de_DE@euro/g' /etc/locale.gen && sudo locale-gen de_DE@euro - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Delete composer lock file - id: composer-lock - if: ${{ matrix.php-version == 'nightly' }} - run: | - rm composer.lock - echo "flags=--ignore-platform-reqs" >> $GITHUB_OUTPUT - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader ${{ steps.composer-lock.outputs.flags }} - - - name: Setup problem matchers for PHP - run: echo "::add-matcher::${{ runner.tool_cache }}/php.json" - - - name: Setup problem matchers for PHPUnit - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: "Run PHPUnit tests (Experimental: ${{ matrix.experimental }})" - env: - FAILURE_ACTION: "${{ matrix.experimental == true }}" - run: vendor/bin/phpunit --display-incomplete --display-skipped --display-deprecations --display-errors --display-notices --display-warnings || $FAILURE_ACTION - - phpdoc-types: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - - # This is non-ideal because it only checks for the last commit of the PR, not all of them, but better than nothing - - name: Check PHPDoc types - run: ./bin/check-phpdoc-types.php - - php-cs-fixer: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code style with PHP-CS-Fixer - run: (./vendor/bin/php-cs-fixer fix --dry-run --format=checkstyle | cs2pr) || ./vendor/bin/php-cs-fixer fix --diff --dry-run - - phpcs: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code style with PHP_CodeSniffer - run: ./vendor/bin/phpcs -q --report=checkstyle | cs2pr - - versions: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Code Version Compatibility check with PHP_CodeSniffer - run: ./vendor/bin/phpcs -q --report-width=200 --report=summary,full src/ --standard=PHPCompatibility --runtime-set testVersion 8.1- --exclude=PHPCompatibility.Variables.ForbiddenThisUseContexts - - phpstan: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: none - tools: cs2pr - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Static analysis with PHPStan - run: ./vendor/bin/phpstan analyse - - coverage: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Install locales - run: sudo apt-get update && sudo apt-get install -y language-pack-fr language-pack-de - - - name: Install single-byte locale - run: sudo sed -i -e 's/# de_DE@euro/de_DE@euro/g' /etc/locale.gen && sudo locale-gen de_DE@euro - - - name: Setup PHP, with composer and extensions - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - extensions: ctype, dom, gd, iconv, fileinfo, libxml, mbstring, simplexml, xml, xmlreader, xmlwriter, zip, zlib - coverage: pcov - - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Cache composer dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-composer- - - - name: Install dependencies - run: composer install --no-progress --prefer-dist --optimize-autoloader - - - name: Coverage - run: | - ./vendor/bin/phpunit --coverage-clover coverage-clover.xml - composer global require scrutinizer/ocular - ~/.composer/vendor/bin/ocular code-coverage:upload --format=php-clover coverage-clover.xml - - release: - permissions: - contents: write # to create a release (actions/create-release) - runs-on: ubuntu-latest - if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.ref }} # Otherwise our annotated tag is not fetched and we cannot get correct version - - - name: Get release info - run: git tag --format '%(contents:body)' --points-at > release-body.txt - - - uses: ncipollo/release-action@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - bodyFile: release-body.txt diff --git a/.gitignore b/.gitignore index eac08567d9..011328ed9a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,12 +2,10 @@ /analysis /vendor/ /phpunit.xml +/.php_cs.cache ## IDE support *.buildpath *.project /.settings /.idea - -## mkdocs output -/site diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php deleted file mode 100644 index 8409a17b09..0000000000 --- a/.php-cs-fixer.dist.php +++ /dev/null @@ -1,245 +0,0 @@ -exclude(['vendor', 'docs', '.git', '.github']) - ->notPath('src/PhpSpreadsheet/Writer/ZipStream3.php') - ->in(__DIR__); - -$config = new PhpCsFixer\Config(); -$config - ->setRiskyAllowed(true) - ->setFinder($finder) - ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect(null, 600)) - ->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_lines_before_namespace' => ['max_line_breaks' => 2, 'min_line_breaks' => 2], // we want 1 blank line before namespace - 'blank_line_after_opening_tag' => true, - 'blank_line_before_statement' => true, - 'cast_spaces' => true, - 'class_attributes_separation' => ['elements' => ['method' => 'one', 'property' => 'one']], // const are often grouped with other related const - 'class_definition' => false, // phpcs disagree - 'combine_consecutive_issets' => true, - 'combine_consecutive_unsets' => true, - 'combine_nested_dirname' => true, - 'comment_to_phpdoc' => false, // interferes with annotations - 'compact_nullable_type_declaration' => 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, - 'doctrine_annotation_array_assignment' => true, - 'doctrine_annotation_braces' => true, - 'doctrine_annotation_indentation' => true, - 'doctrine_annotation_spaces' => true, - 'elseif' => true, - 'empty_loop_body' => true, - 'empty_loop_condition' => true, - 'encoding' => true, - 'ereg_to_preg' => true, - 'error_suppression' => false, // it breaks \PhpOffice\PhpSpreadsheet\Helper\Handler - '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 - 'fopen_flag_order' => true, - 'fopen_flags' => true, - 'full_opening_tag' => true, - 'fully_qualified_strict_types' => true, - 'function_declaration' => true, - 'function_to_constant' => true, - 'general_phpdoc_annotation_remove' => ['annotations' => ['access', 'category', 'copyright']], - 'general_phpdoc_tag_rename' => true, - 'global_namespace_import' => true, - 'group_import' => false, // I feel it makes the code actually harder to read - 'header_comment' => false, // We don't use common header in all our files - 'heredoc_indentation' => true, - 'heredoc_to_nowdoc' => false, // Not sure about this one - 'implode_call' => true, - 'include' => true, - 'increment_style' => true, - 'indentation_type' => true, - 'integer_literal_case' => true, - 'is_null' => true, - 'lambda_not_used_import' => true, - 'line_ending' => true, - 'linebreak_after_opening_tag' => true, - 'list_syntax' => ['syntax' => 'short'], - 'logical_operators' => true, - 'lowercase_cast' => true, - '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, - 'modernize_strpos' => true, - '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, // I suppose this would be best, but I am still unconvinced about the visual aspect of it - 'new_with_parentheses' => ['anonymous_class' => true, 'named_class' => true], - 'no_alias_functions' => true, - 'no_alias_language_construct_call' => true, - 'no_alternative_syntax' => true, - 'no_binary_string' => true, - 'no_blank_lines_after_class_opening' => true, - 'no_blank_lines_after_phpdoc' => true, - 'no_break_comment' => true, - 'no_closing_tag' => true, - 'no_empty_comment' => true, - 'no_empty_phpdoc' => true, - 'no_empty_statement' => true, - 'no_extra_blank_lines' => true, - 'no_homoglyph_names' => true, - 'no_leading_import_slash' => true, - 'no_leading_namespace_whitespace' => true, - 'no_mixed_echo_print' => true, - 'no_multiline_whitespace_around_double_arrow' => true, - 'no_null_property_initialization' => true, - 'no_php4_constructor' => true, - 'no_short_bool_cast' => true, - 'echo_tag_syntax' => ['format' => 'long'], - 'no_singleline_whitespace_before_semicolons' => true, - 'no_space_around_double_colon' => true, - 'no_spaces_after_function_name' => true, - 'no_spaces_around_offset' => true, - 'no_superfluous_elseif' => false, // Might be risky on a huge code base - 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], - 'no_trailing_comma_in_singleline' => ['elements' => ['arguments', 'array_destructuring', 'array', 'group_import']], - 'no_trailing_whitespace' => true, - 'no_trailing_whitespace_in_comment' => true, - 'no_trailing_whitespace_in_string' => false, // Too dangerous - 'no_unneeded_control_parentheses' => true, - 'no_unneeded_braces' => true, - 'no_unneeded_final_method' => true, - 'no_unreachable_default_argument_value' => true, - 'no_unset_cast' => true, - 'no_unset_on_property' => false, - 'no_unused_imports' => true, - 'no_useless_else' => true, - 'no_useless_return' => true, - 'no_useless_sprintf' => 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, - 'octal_notation' => true, - 'operator_linebreak' => true, - 'ordered_class_elements' => false, // We prefer to keep some freedom - 'ordered_imports' => true, - 'ordered_interfaces' => true, - 'ordered_traits' => true, - 'php_unit_attributes' => ['keep_annotations' => false], - '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, - 'phpdoc_order_by_value' => ['annotations' => ['covers']], - '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' => false, // Don't add things that bring no value - 'phpdoc_align' => false, // Waste of time - 'phpdoc_annotation_without_dot' => true, - 'phpdoc_indent' => 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, - 'phpdoc_no_package' => true, - 'phpdoc_no_useless_inheritdoc' => true, - 'phpdoc_order' => true, - 'phpdoc_return_self_reference' => true, - 'phpdoc_scalar' => true, - 'phpdoc_separation' => true, - 'phpdoc_single_line_var_spacing' => true, - 'phpdoc_summary' => true, - 'phpdoc_tag_casing' => true, - 'phpdoc_tag_type' => true, - 'phpdoc_to_comment' => false, // interferes with annotations - 'phpdoc_to_param_type' => false, // Because experimental, but interesting for one shot use - 'phpdoc_to_property_type' => false, // Because experimental, but interesting for one shot use - 'phpdoc_to_return_type' => false, // Because experimental, but interesting for one shot use - 'phpdoc_trim' => 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, - 'pow_to_exponentiation' => true, - 'protected_to_private' => true, - 'psr_autoloading' => true, - '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, - 'simple_to_complex_string_variable' => false, // Would differ from TypeScript without obvious advantages - 'simplified_if_return' => false, // Even if technically correct we prefer to be explicit - 'simplified_null_return' => false, // Even if technically correct we prefer to be explicit - 'single_blank_line_at_eof' => 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, - 'spaces_inside_parentheses' => ['space' => 'none'], - '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 - 'string_implicit_backslashes' => ['single_quoted' => 'unescape', 'double_quoted' => 'escape', 'heredoc' => 'escape'], // was escape_implicit_backslashes - 'strict_param' => false, // No, too dangerous to change that - 'string_length_to_empty' => true, - 'string_line_ending' => true, - 'switch_case_semicolon_to_colon' => true, - 'switch_case_space' => true, - 'switch_continue_to_break' => true, - 'ternary_operator_spaces' => true, - 'ternary_to_elvis_operator' => true, - 'ternary_to_null_coalescing' => true, - 'trailing_comma_in_multiline' => true, - 'trim_array_spaces' => true, - 'type_declaration_spaces' => ['elements' => ['function', 'property']], // was function_typehint_space - 'types_spaces' => true, - 'unary_operator_spaces' => true, - 'use_arrow_functions' => true, - 'visibility_required' => ['elements' => ['property', 'method']], // not const - 'void_return' => true, - 'whitespace_after_comma_in_array' => true, - 'yoda_style' => false, - ]); - -return $config; diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000000..5a494b87a7 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,181 @@ +exclude('vendor') + ->in('samples') + ->in('src') + ->in('tests'); + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setFinder($finder) + ->setRules([ + 'align_multiline_comment' => true, + 'array_syntax' => ['syntax' => 'short'], + 'backtick_to_shell_exec' => true, + 'binary_operator_spaces' => true, + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_before_statement' => true, + 'braces' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => ['elements' => ['method', 'property']], // const are often grouped with other related const + 'class_definition' => true, + 'class_keyword_remove' => false, // ::class keyword gives us beter support in IDE + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => true, + 'declare_strict_types' => false, // Too early to adopt strict types + 'dir_constant' => true, + 'doctrine_annotation_array_assignment' => true, + 'doctrine_annotation_braces' => true, + 'doctrine_annotation_indentation' => true, + 'doctrine_annotation_spaces' => true, + 'elseif' => true, + 'encoding' => true, + 'ereg_to_preg' => true, + 'escape_implicit_backslashes' => true, + 'explicit_indirect_variable' => false, // I feel it makes the code actually harder to read + 'explicit_string_variable' => false, // I feel it makes the code actually harder to read + 'final_internal_class' => true, + 'full_opening_tag' => true, + 'function_declaration' => true, + 'function_to_constant' => true, + 'function_typehint_space' => true, + 'general_phpdoc_annotation_remove' => false, // No use for that + 'hash_to_slash_comment' => true, + 'header_comment' => false, // We don't use common header in all our files + 'heredoc_to_nowdoc' => false, // Not sure about this one + 'include' => true, + 'increment_style' => true, + 'indentation_type' => true, + 'is_null' => ['use_yoda_style' => false], + 'linebreak_after_opening_tag' => true, + 'line_ending' => true, + 'list_syntax' => ['syntax' => 'long'], // Stay compatiblew with PHP 5.6 + 'lowercase_cast' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'magic_constant_casing' => true, + 'mb_str_functions' => false, // No, too dangerous to change that + 'method_argument_space' => true, + 'method_chaining_indentation' => true, + 'method_separation' => true, + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'native_function_casing' => true, + 'native_function_invocation' => false, // This is risky and seems to be micro-optimization that make code uglier so not worth it, at least for now + 'new_with_braces' => true, + 'no_alias_functions' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => false, // we want 1 blank line before namespace + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => true, + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_multiline_whitespace_before_semicolons' => true, + 'non_printable_character' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'normalize_index_brace' => true, + 'no_short_bool_cast' => true, + 'no_short_echo_tag' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => false, // Might be risky on a huge code base + 'not_operator_with_space' => false, // No we prefer to keep '!' without spaces + 'not_operator_with_successor_space' => false, // idem + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_trailing_whitespace' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => false, // We prefer to keep some freedom + 'ordered_imports' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => false, // Waste of time + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_inline_tag' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_no_useless_inheritdoc' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_summary' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_types_order' => true, + 'phpdoc_types' => true, + 'phpdoc_var_without_name' => true, + 'php_unit_construct' => true, + 'php_unit_dedicate_assert' => true, + 'php_unit_expectation' => true, + 'php_unit_fqcn_annotation' => true, + 'php_unit_mock' => true, + 'php_unit_namespaced' => true, + 'php_unit_no_expectation_annotation' => true, + 'php_unit_strict' => false, // We sometime actually need assertEquals + 'php_unit_test_annotation' => true, + 'php_unit_test_class_requires_covers' => false, // We don't care as much as we should about coverage + 'pow_to_exponentiation' => false, + 'protected_to_private' => true, + 'psr0' => true, + 'psr4' => true, + 'random_api_migration' => false, // This breaks our unit tests + 'return_type_declaration' => true, + 'self_accessor' => true, + 'semicolon_after_instruction' => false, // Buggy in `samples/index.php` + 'short_scalar_cast' => true, + 'silenced_deprecation_error' => true, + 'simplified_null_return' => false, // While technically correct we prefer to be explicit when returning null + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_style' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'standardize_not_equals' => true, + 'static_lambda' => false, // Risky if we can't guarantee nobody use `bindTo()` + 'strict_comparison' => false, // No, too dangerous to change that + 'strict_param' => false, // No, too dangerous to change that + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'ternary_to_null_coalescing' => false, // Cannot use that with PHP 5.6 + 'trailing_comma_in_multiline_array' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => true, + 'void_return' => false, // Cannot use that with PHP 5.6 + 'whitespace_after_comma_in_array' => true, + 'yoda_style' => false, + ]); diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist deleted file mode 100644 index 69f2bc6f49..0000000000 --- a/.phpcs.xml.dist +++ /dev/null @@ -1,21 +0,0 @@ - - - - samples - src - tests - infra - bin - - - - - - - - - - - - diff --git a/.readthedocs.yaml b/.readthedocs.yaml deleted file mode 100644 index c67101532d..0000000000 --- a/.readthedocs.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Read the Docs configuration file for MkDocs projects -# See https://docs.readthedocs.io/en/stable/config-file/v2.html - -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3" - -mkdocs: - configuration: mkdocs.yml diff --git a/.sami.php b/.sami.php new file mode 100644 index 0000000000..9a2fca3534 --- /dev/null +++ b/.sami.php @@ -0,0 +1,24 @@ +files() + ->name('*.php') + ->in($dir = __DIR__ . '/src'); +$versions = GitVersionCollection::create($dir) + ->addFromTags(function ($version) { + return preg_match('~^\d+\.\d+\.\d+$~', $version); + }) + ->add('master'); + +return new Sami($iterator, [ + 'title' => 'PhpSpreadsheet', + 'versions' => $versions, + 'build_dir' => __DIR__ . '/build/%version%', + 'cache_dir' => __DIR__ . '/cache/%version%', + 'remote_repository' => new GitHubRemoteRepository('PHPOffice/PhpSpreadsheet', dirname($dir)), +]); diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 78ff6867d1..748f3ac3fa 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -12,19 +12,16 @@ coding_style: build: nodes: analysis: - image: default-bionic - environment: - php: 8.2 tests: override: - php-scrutinizer-run tools: external_code_coverage: - timeout: 600 + timeout: 3600 build_failure_conditions: - - 'elements.rating(<= D).new.exists' # No new classes/methods with a rating of D or worse allowed + - 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed - 'issues.severity(>= MAJOR).new.exists' # New issues of major or higher severity - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection - 'patches.label("Unused Use Statements").new.exists' # No new unused imports patches allowed diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..3a94e663e9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,59 @@ +language: php +dist: trusty +sudo: false + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + +cache: + directories: + - cache + - vendor + - $HOME/.composer/cache + +before_script: + # Deactivate xdebug + - if [ -z "$KEEP_XDEBUG" ]; then rm -rfv /home/travis/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ; fi + - composer install --ignore-platform-reqs + +script: + - ./vendor/bin/phpunit + +jobs: + include: + + - stage: Code style + php: 7.1 + script: + - ./vendor/bin/php-cs-fixer fix --diff --verbose --dry-run + - ./vendor/bin/phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n + + - stage: Coverage + php: 7.1 + env: KEEP_XDEBUG=1 + script: + - travis_wait 40 ./vendor/bin/phpunit --debug --coverage-clover coverage-clover.xml + after_script: + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover tests/coverage-clover.xml + + - stage: API documentation + php: 7.1 + before_script: + - curl -O http://get.sensiolabs.org/sami.phar + script: + - git fetch origin master:master + - git fetch origin --tags + - php sami.phar update .sami.php + - echo '

If you are not automatically redirected, please go to the latest stable API documentation.

' > build/index.html + deploy: + provider: pages + skip-cleanup: true + local-dir: build + github-token: $GITHUB_TOKEN + on: + all_branches: true + condition: $TRAVIS_BRANCH =~ ^master|develop$ diff --git a/CHANGELOG.PHPExcel.md b/CHANGELOG.PHPExcel.md index 3c299020ed..a32f78b56c 100644 --- a/CHANGELOG.PHPExcel.md +++ b/CHANGELOG.PHPExcel.md @@ -103,7 +103,7 @@ confused with PhpSpreadsheet versions. - Convert properties to string in OOCalc reader - @infojunkie [#276](https://github.com/PHPOffice/PHPExcel/issues/276) - Disable libxml external entity loading by default. - @maartenba [#322](https://github.com/PHPOffice/PHPExcel/issues/322) - - This is to prevent XML External Entity Processing (XXE) injection attacks (see https://websec.io/2012/08/27/Preventing-XEE-in-PHP.html for an explanation of XXE injection). + - This is to prevent XML External Entity Processing (XXE) injection attacks (see http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html for an explanation of XXE injection). - Reference CVE-2014-2054 ## [1.7.9] - 2013-06-02 diff --git a/CHANGELOG.md b/CHANGELOG.md index 05b6bf0d31..ea77fe88e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,1724 +2,33 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com) -and this project adheres to [Semantic Versioning](https://semver.org). +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). -## TBD - 4.4.0 - -### Added - -- VSTACK and HSTACK. [Issue #4485](https://github.com/PHPOffice/PhpSpreadsheet/issues/4485) [PR #4492](https://github.com/PHPOffice/PhpSpreadsheet/pull/4492) -- TOCOL and TOROW. [PR #4493](https://github.com/PHPOffice/PhpSpreadsheet/pull/4493) -- Support Current Office Theme. [PR #4500](https://github.com/PHPOffice/PhpSpreadsheet/pull/4500) - -### Removed - -- Nothing yet. - -### Changed - -- Nothing yet. - -### Moved - -- Nothing yet. - -### Deprecated - -- Theme constants COLOR_SCHEME_2013_PLUS_NAME (use COLOR_SCHEME_2013_2022_NAME) and COLOR_SCHEME_2013_PLUS (use COLOR_SCHEME_2013_2022). - -### Fixed - -- Various Writers RichText TextElement Should Inherit Cell Style. [Issue #1154](https://github.com/PHPOffice/PhpSpreadsheet/issues/1154) [PR #4487](https://github.com/PHPOffice/PhpSpreadsheet/pull/4487) -- Minor Changes to FILTER function. [PR #4491](https://github.com/PHPOffice/PhpSpreadsheet/pull/4491) -- Allow Xlsx Reader/Writer to support Font Charset. [Issue #2760](https://github.com/PHPOffice/PhpSpreadsheet/issues/2760) [PR #4501](https://github.com/PHPOffice/PhpSpreadsheet/pull/4501) -- AutoColor for LibreOffice Dark Mode [Discussion 4502](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4502) [PR #4503](https://github.com/PHPOffice/PhpSpreadsheet/pull/4503) -- Xlsx Style Writer Minor Refactoring. [PR #4508](https://github.com/PHPOffice/PhpSpreadsheet/pull/4508) - -## 2025-05-26 - 4.3.1 - -### Fixed - -- Regression in Date::stringToExcel. [Issue #4488](https://github.com/PHPOffice/PhpSpreadsheet/issues/4488) [PR #4489](https://github.com/PHPOffice/PhpSpreadsheet/pull/4489) - -## 2025-05-25 - 4.3.0 - -### Added - -- Xml Reader recognize indents. [Issue #4448](https://github.com/PHPOffice/PhpSpreadsheet/issues/4448) [PR #4449](https://github.com/PHPOffice/PhpSpreadsheet/pull/4449) - -### Changed - -- Phpstan Level 10. - -### Fixed - -- Micro-optimization for excelToDateTimeObject. [Issue #4438](https://github.com/PHPOffice/PhpSpreadsheet/issues/4438) [PR #4442](https://github.com/PHPOffice/PhpSpreadsheet/pull/4442) -- Removing Columns/Rows Containing Merged Cells. [Issue #282](https://github.com/PHPOffice/PhpSpreadsheet/issues/282) [PR #4465](https://github.com/PHPOffice/PhpSpreadsheet/pull/4465) -- Print Area and Row Break. [Issue #1275](https://github.com/PHPOffice/PhpSpreadsheet/issues/1275) [PR #4450](https://github.com/PHPOffice/PhpSpreadsheet/pull/4450) -- Copy Styles after insertNewColumnBefore. [Issue #1425](https://github.com/PHPOffice/PhpSpreadsheet/issues/1425) [PR #4468](https://github.com/PHPOffice/PhpSpreadsheet/pull/4468) -- Xls Writer Treat Hyperlink Starting with # as Internal. [Issue #56](https://github.com/PHPOffice/PhpSpreadsheet/issues/56) [PR #4453](https://github.com/PHPOffice/PhpSpreadsheet/pull/4453) -- More Precision for Float to String Casts. [Issue #3899](https://github.com/PHPOffice/PhpSpreadsheet/issues/3899) [PR #4479](https://github.com/PHPOffice/PhpSpreadsheet/pull/4479) -- Hyperlink Styles. [Issue #1632](https://github.com/PHPOffice/PhpSpreadsheet/issues/1632) [PR #4478](https://github.com/PHPOffice/PhpSpreadsheet/pull/4478) -- ODS Handling of Ceiling and Floor. [Issue #477](https://github.com/PHPOffice/PhpSpreadsheet/issues/407) [PR #4466](https://github.com/PHPOffice/PhpSpreadsheet/pull/4466) -- Xlsx Reader Do Not Process Printer Settings for Dataonly. [Issue #4477](https://github.com/PHPOffice/PhpSpreadsheet/issues/4477) [PR #4480](https://github.com/PHPOffice/PhpSpreadsheet/pull/4480) - -## 2025-04-16 - 4.2.0 - -### Added - -- Add ability to add custom functions to Calculation. [PR #4390](https://github.com/PHPOffice/PhpSpreadsheet/pull/4390) -- Add FormulaRange to IgnoredErrors. [PR #4393](https://github.com/PHPOffice/PhpSpreadsheet/pull/4393) -- TextGrid improvements. [PR #4418](https://github.com/PHPOffice/PhpSpreadsheet/pull/4418) -- Permit read to class which extends Spreadsheet. [Discussion #4402](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4402) [PR #4404](https://github.com/PHPOffice/PhpSpreadsheet/pull/4404) -- Conditional and table formatting support for html writer [PR #4412](https://github.com/PHPOffice/PhpSpreadsheet/pull/4412) - -### Changed - -- Phpstan Version 2. [PR #4384](https://github.com/PHPOffice/PhpSpreadsheet/pull/4384) -- Start migration to Phpstan level 9. [PR #4396](https://github.com/PHPOffice/PhpSpreadsheet/pull/4396) -- Calculation locale logic moved to separate class. [PR #4398](https://github.com/PHPOffice/PhpSpreadsheet/pull/4398) -- TREND_POLYNOMIAL_* and TREND_BEST_FIT do not work, and are changed to throw Exceptions if attempted. (TREND_BEST_FIT_NO_POLY works.) An attempt to use an unknown trend type will now also throw an exception. [Issue #4400](https://github.com/PHPOffice/PhpSpreadsheet/issues/4400) [PR #4339](https://github.com/PHPOffice/PhpSpreadsheet/pull/4339) -- Month parameter of DATE function will now return VALUE if an ordinal string (e.g. '3rd') is used, but will accept bool or null. [PR #4420](https://github.com/PHPOffice/PhpSpreadsheet/pull/4420) - -### Fixed - -- Ignore fractional part of Drawing Shadow Alpha. [Issue #4415](https://github.com/PHPOffice/PhpSpreadsheet/issues/4415) [PR #4417](https://github.com/PHPOffice/PhpSpreadsheet/pull/4417) -- BIN2DEC, OCT2DEC, and HEX2DEC return numbers rather than strings. [Issue #4383](https://github.com/PHPOffice/PhpSpreadsheet/issues/4383) [PR #4389](https://github.com/PHPOffice/PhpSpreadsheet/pull/4389) -- Fix TREND_BEST_FIT_NO_POLY. [Issue #4400](https://github.com/PHPOffice/PhpSpreadsheet/issues/4400) [PR #4339](https://github.com/PHPOffice/PhpSpreadsheet/pull/4339) -- Ods Reader No DataType for Null Value. [Issue #4435](https://github.com/PHPOffice/PhpSpreadsheet/issues/4435) [PR #4436](https://github.com/PHPOffice/PhpSpreadsheet/pull/4436) -- Column widths not preserved when using read filter. [Issue #4416](https://github.com/PHPOffice/PhpSpreadsheet/issues/4416) [PR #4423](https://github.com/PHPOffice/PhpSpreadsheet/pull/4423) -- Fix typo in Style exportArray quotePrefix. [Issue #4422](https://github.com/PHPOffice/PhpSpreadsheet/issues/4422) [PR #4424](https://github.com/PHPOffice/PhpSpreadsheet/pull/4424) -- Tweak Spreadsheet clone. [PR #4419](https://github.com/PHPOffice/PhpSpreadsheet/pull/4419) -- Better handling of Chart DisplayBlanksAs. [Issue #4411](https://github.com/PHPOffice/PhpSpreadsheet/issues/4411) [PR #4414](https://github.com/PHPOffice/PhpSpreadsheet/pull/4414) - -## 2025-03-02 - 4.1.0 - -### Added - -- Support Justify Last Line. [Issue #4374](https://github.com/PHPOffice/PhpSpreadsheet/issues/4374) [PR #4373](https://github.com/PHPOffice/PhpSpreadsheet/pull/4373) -- Allow Spreadsheet clone. [PR #4370](https://github.com/PHPOffice/PhpSpreadsheet/pull/4370) - -### Changed - -- ListWorksheetInfo will now return sheetState (visible, hidden, veryHidden). [Issue #4345](https://github.com/PHPOffice/PhpSpreadsheet/issues/4345) [PR #4366](https://github.com/PHPOffice/PhpSpreadsheet/pull/4366) -- Start migration to Phpstan 2. [PR #4359](https://github.com/PHPOffice/PhpSpreadsheet/pull/4359) -- IOFactory identify can return, and createReader and CreateWriter can accept, a class name rather than a file type. [Issue #4357](https://github.com/PHPOffice/PhpSpreadsheet/issues/4357) [PR #4361](https://github.com/PHPOffice/PhpSpreadsheet/pull/4361) - -### Fixed - -- Refactor Helper/Html. [PR #4359](https://github.com/PHPOffice/PhpSpreadsheet/pull/4359) -- Handle #REF! as Argument to AVERAGEIF/COUNTIF/SUMIF. [Issue #4381](https://github.com/PHPOffice/PhpSpreadsheet/issues/4381) [PR #4382](https://github.com/PHPOffice/PhpSpreadsheet/pull/4382) -- Ignore ignoredErrors when not applicable. [Issue #4375](https://github.com/PHPOffice/PhpSpreadsheet/issues/4375) [PR #4377](https://github.com/PHPOffice/PhpSpreadsheet/pull/4377) -- Better handling of defined names on sheets whose titles include apostrophes. [Issue #4356](https://github.com/PHPOffice/PhpSpreadsheet/issues/4356) [Issue #4362](https://github.com/PHPOffice/PhpSpreadsheet/issues/4362) [Issue #4376](https://github.com/PHPOffice/PhpSpreadsheet/issues/4376) [PR #4360](https://github.com/PHPOffice/PhpSpreadsheet/pull/4360) -- Partial solution for removing rows or columns that include edge ranges. [Issue #1449](https://github.com/PHPOffice/PhpSpreadsheet/issues/1449) [PR #3528](https://github.com/PHPOffice/PhpSpreadsheet/pull/3528) -- Prefer mb_str_split to str_split. [PR #3341](https://github.com/PHPOffice/PhpSpreadsheet/pull/3341) - -## 2025-02-08 - 4.0.0 - -### BREAKING CHANGES - -- Data Validations will be stored by worksheet, not cell. Index can be one or more cells or cell ranges. [Issue #797](https://github.com/PHPOffice/PhpSpreadsheet/issues/797) [Issue #4091](https://github.com/PHPOffice/PhpSpreadsheet/issues/4091) [Issue #4206](https://github.com/PHPOffice/PhpSpreadsheet/issues/4206) [PR #4240](https://github.com/PHPOffice/PhpSpreadsheet/pull/4240) -- Conditional Formatting adds Priority property and handles overlapping ranges better. [Issue #4312](https://github.com/PHPOffice/PhpSpreadsheet/issues/4312) [Issue #4318](https://github.com/PHPOffice/PhpSpreadsheet/issues/4318) [PR #4314](https://github.com/PHPOffice/PhpSpreadsheet/pull/4314) -- Csv Reader will no longer auto-detect Mac line endings by default. Prior behavior can be explicitly enabled via `setTestAutoDetect(true)`, and it will not be possible at all with Php9+. [Issue #4092](https://github.com/PHPOffice/PhpSpreadsheet/issues/4092) [PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340) -- Html Writer will now use "better boolean" logic. Booleans will now be output by default as TRUE/FALSE rather than 1/null-string. Prior behavior can be explicitly enabled via `setBetterBoolean(false)`. [PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340) -- Xlsx Writer will now use false as the default for `forceFullCalc`. This affects writes with `preCalculateFormulas` set to false. Prior behavior can be explicitly enabled via `setForceFullCalc(null)`.[PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340) -- Deletion of items deprecated in Release 3. See "removed" below. - -### Added - -- Pdf Charts and Drawings. [Discussion #4129](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4129) [Discussion #4168](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4168) [PR #4327](https://github.com/PHPOffice/PhpSpreadsheet/pull/4327) -- Allow spreadsheet serialization. [Discussion #4324](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4324) [Issue #1741](https://github.com/PHPOffice/PhpSpreadsheet/issues/1741) [Issue #1757](https://github.com/PHPOffice/PhpSpreadsheet/issues/1757) [PR #4326](https://github.com/PHPOffice/PhpSpreadsheet/pull/4326) - -### Removed - -- Worksheet::getStyles - no replacement. [PR #4330](https://github.com/PHPOffice/PhpSpreadsheet/pull/4330) -- The following items were deprecated in release 3 and are now removed. -- Drawing::setIsUrl - no replacement. -- Settings::setLibXmlLoaderOptions() and Settings::getLibXmlLoaderOptions() - no replacement. -- Worksheet::getHashCode - no replacement. -- IReader::SKIP_EMPTY_CELLS - use its alias IGNORE_EMPTY_CELLS instead. -- Worksheet::getProtectedCells - use getProtectedCellRanges instead. -- Writer/Html::isMpdf property - use instanceof Mpdf instead. - -### Changed - -- Nothing yet. - -### Moved - -- Nothing yet. - -### Deprecated - -- Nothing yet. - -### Fixed - -- Xls writer Parser Mishandling True/False Argument. [Issue #4331](https://github.com/PHPOffice/PhpSpreadsheet/issues/4331) [PR #4333](https://github.com/PHPOffice/PhpSpreadsheet/pull/4333) -- Xls writer Parser Parse By Character Not Byte. [PR #4344](https://github.com/PHPOffice/PhpSpreadsheet/pull/4344) -- Minor changes to dynamic array calculations exposed by using explicit array return types in some tests. [PR #4328](https://github.com/PHPOffice/PhpSpreadsheet/pull/4328) - -## 2025-01-26 - 3.9.0 - -### Added - -- Methods to get style for row or column. [PR #4317](https://github.com/PHPOffice/PhpSpreadsheet/pull/4317) -- Method for duplicating worksheet in spreadsheet. [PR #4315](https://github.com/PHPOffice/PhpSpreadsheet/pull/4315) - -### Fixed - -- Security patch for control characters in protocol. -- Ods Reader Sheet Names with Period. [Issue #4311](https://github.com/PHPOffice/PhpSpreadsheet/issues/4311) [PR #4313](https://github.com/PHPOffice/PhpSpreadsheet/pull/4313) -- Mpdf and Tcpdf Hidden Columns and Merged Cells. [Issue #4319](https://github.com/PHPOffice/PhpSpreadsheet/issues/4319) [PR #4320](https://github.com/PHPOffice/PhpSpreadsheet/pull/4320) -- Html Writer Allow mailto. [Issue #4316](https://github.com/PHPOffice/PhpSpreadsheet/issues/4316) [PR #4322](https://github.com/PHPOffice/PhpSpreadsheet/pull/4322) -- Use composer/pcre rather than preg_* in Writer. [PR #4323](https://github.com/PHPOffice/PhpSpreadsheet/pull/4323) - -## 2025-01-11 - 3.8.0 - -### Added - -- CHOOSECOLS, CHOOSEROWS, DROP, TAKE, and EXPAND. [PR #4286](https://github.com/PHPOffice/PhpSpreadsheet/pull/4286) - -### Fixed - -- Security patch for Html navigation. -- Xlsx Reader Shared Formula with Boolean Result. Partial solution for [Issue #4280](https://github.com/PHPOffice/PhpSpreadsheet/issues/4280) [PR #4281](https://github.com/PHPOffice/PhpSpreadsheet/pull/4281) -- Retitling cloned Worksheets. [Issue #641](https://github.com/PHPOffice/PhpSpreadsheet/issues/641) [PR #4302](https://github.com/PHPOffice/PhpSpreadsheet/pull/4302) -- Extremely limited support for GROUPBY function. Partial response to [Issue #4282](https://github.com/PHPOffice/PhpSpreadsheet/issues/4282) [PR #4283](https://github.com/PHPOffice/PhpSpreadsheet/pull/4283) - -## 2024-12-26 - 3.7.0 - -### Deprecated - -- Drawing::setIsUrl is unneeded. The property is set when setPath determines whether path is a url. - -### Fixed - -- Security patches for Samples. -- Security patches for Html Writer. -- Avoid unexpected charset in currency symbol. [PR #4279](https://github.com/PHPOffice/PhpSpreadsheet/pull/4279) -- Add forceFullCalc option to Xlsx Writer. [Issue #4269](https://github.com/PHPOffice/PhpSpreadsheet/issues/4269) [PR #4271](https://github.com/PHPOffice/PhpSpreadsheet/pull/4271) -- More context options may be needed for http(s) image. [Php issue 17121](https://github.com/php/php-src/issues/17121) [PR #4276](https://github.com/PHPOffice/PhpSpreadsheet/pull/4276) -- Coverage-related tweaks to Xls Reader. [PR #4277](https://github.com/PHPOffice/PhpSpreadsheet/pull/4277) -- Several fixed to ODS Writer. [Issue #4261](https://github.com/PHPOffice/PhpSpreadsheet/issues/4261) [PR #4263](https://github.com/PHPOffice/PhpSpreadsheet/pull/4263) [PR #4264](https://github.com/PHPOffice/PhpSpreadsheet/pull/4264) [PR #4266](https://github.com/PHPOffice/PhpSpreadsheet/pull/4266) - -## 2024-12-08 - 3.6.0 - -### Added - -- Nothing yet. - -### Changed - -- Nothing yet. - -### Moved - -- Nothing yet. - -### Deprecated - -- Nothing yet. - -### Fixed - -- Html Reader/Writer Better Handling of Booleans. [PR #4257](https://github.com/PHPOffice/PhpSpreadsheet/pull/4257) -- Fill Patterns/Colors When Xml Attributes are Missing. [Issue #4248](https://github.com/PHPOffice/PhpSpreadsheet/issues/4248) [PR #4250](https://github.com/PHPOffice/PhpSpreadsheet/pull/4250) -- Remove Unneccesary files from Composer Package. [PR #4262](https://github.com/PHPOffice/PhpSpreadsheet/pull/4262) -- Swapped row and column indexes in ReferenceHelper. [Issue #4246](https://github.com/PHPOffice/PhpSpreadsheet/issues/4246) [PR #4247](https://github.com/PHPOffice/PhpSpreadsheet/pull/4247) -- Fix minor break handling drawings. [Issue #4241](https://github.com/PHPOffice/PhpSpreadsheet/issues/4241) [PR #4244](https://github.com/PHPOffice/PhpSpreadsheet/pull/4244) -- Ignore cell formatting when the format is a single @. [Issue #4242](https://github.com/PHPOffice/PhpSpreadsheet/issues/4242) [PR #4243](https://github.com/PHPOffice/PhpSpreadsheet/pull/4243) -- Upgrade Dompdf to Php-8.4 compatible version [PR #4267](https://github.com/PHPOffice/PhpSpreadsheet/pull/4267) - -## 2024-11-22 - 3.5.0 - -### Added - -- Nothing yet. - -### Changed - -- Settings::libXmlLoaderOptions is ignored. [PR #4233](https://github.com/PHPOffice/PhpSpreadsheet/pull/4233) - -### Moved - -- Nothing yet. - -### Deprecated - -- Settings::setLibXmlLoaderOptions() and Settings::getLibXmlLoaderOptions() are no longer needed - no replacement. -- Worksheet::getHashCode is no longer needed. - -### Fixed - -- Add support for `` tag when converting HTML to RichText. [Issue #4223](https://github.com/PHPOffice/PhpSpreadsheet/issues/4223) [PR #4224](https://github.com/PHPOffice/PhpSpreadsheet/pull/4224) -- Change hash code for worksheet. [Issue #4192](https://github.com/PHPOffice/PhpSpreadsheet/issues/4192) [PR #4207](https://github.com/PHPOffice/PhpSpreadsheet/pull/4207) - -## 2024-11-10 - 3.4.0 - -### Security Fix - -- Several security patches. - -### Added - -- Add Dynamic valueBinder Property to Spreadsheet and Readers. [Issue #1395](https://github.com/PHPOffice/PhpSpreadsheet/issues/1395) [PR #4185](https://github.com/PHPOffice/PhpSpreadsheet/pull/4185) -- Allow Omitting Chart Border. [Issue #562](https://github.com/PHPOffice/PhpSpreadsheet/issues/562) [PR #4188](https://github.com/PHPOffice/PhpSpreadsheet/pull/4188) -- Method to Test Whether Csv Will Be Affected by Php9. [PR #4189](https://github.com/PHPOffice/PhpSpreadsheet/pull/4189) - -### Changed - -- Refactor Xls Reader. [PR #4118](https://github.com/PHPOffice/PhpSpreadsheet/pull/4118) - -### Deprecated - -- IReader::SKIP_EMPTY_CELLS - use its alias IGNORE_EMPTY_CELLS instead. -- Worksheet::getProtectedCells was deprecated in release 2, but was not properly documented, and not removed in release 3. Use getProtectedCellRanges instead. -- Writer/Html::isMpdf property was deprecated in release 2, but was not properly documented, and not removed in release 3. Use instanceof Mpdf instead. - -### Moved - -- Nothing yet. - -### Fixed - -- Xls Writer Condtional Rules Applied to Whole Rows or Columns. [Issue #3185](https://github.com/PHPOffice/PhpSpreadsheet/issues/3185) [PR #4152](https://github.com/PHPOffice/PhpSpreadsheet/pull/4152) -- Xlsx Writer Duplicate ContentTypes Entry for Background Image. [Issue #4179](https://github.com/PHPOffice/PhpSpreadsheet/issues/4179) [PR #4180](https://github.com/PHPOffice/PhpSpreadsheet/pull/4180) -- Check strictNullComparison outside of loops. [PR #3347](https://github.com/PHPOffice/PhpSpreadsheet/pull/3347) -- SUMIFS Does Not Require xlfn. [Issue #4182](https://github.com/PHPOffice/PhpSpreadsheet/issues/4182) [PR #4186](https://github.com/PHPOffice/PhpSpreadsheet/pull/4186) -- Image Transparency/Opacity with Html Reader Changes. [Discussion #4117](https://github.com/PHPOffice/PhpSpreadsheet/discussions/4117) [PR #4142](https://github.com/PHPOffice/PhpSpreadsheet/pull/4142) -- Option to Write Hyperlink Rather Than Label to Csv. [Issue #1412](https://github.com/PHPOffice/PhpSpreadsheet/issues/1412) [PR #4151](https://github.com/PHPOffice/PhpSpreadsheet/pull/4151) -- Invalid Html Due to Cached Filesize. [Issue #1107](https://github.com/PHPOffice/PhpSpreadsheet/issues/1107) [PR #4184](https://github.com/PHPOffice/PhpSpreadsheet/pull/4184) -- Excel 2003 Allows Html Entities. [Issue #2157](https://github.com/PHPOffice/PhpSpreadsheet/issues/2157) [PR #4187](https://github.com/PHPOffice/PhpSpreadsheet/pull/4187) -- Changes to ROUNDDOWN/ROUNDUP/TRUNC. [Issue #4213](https://github.com/PHPOffice/PhpSpreadsheet/issues/4213) [PR #4214](https://github.com/PHPOffice/PhpSpreadsheet/pull/4214) -- Writer Xlsx ignoredErrors Before Drawings. [Issue #4200](https://github.com/PHPOffice/PhpSpreadsheet/issues/4200) [Issue #4145](https://github.com/PHPOffice/PhpSpreadsheet/issues/4145) [PR #4212](https://github.com/PHPOffice/PhpSpreadsheet/pull/4212) -- Allow ANCHORARRAY as Data Validation list. [Issue #4197](https://github.com/PHPOffice/PhpSpreadsheet/issues/4197) [PR #4203](https://github.com/PHPOffice/PhpSpreadsheet/pull/4203) - -## 2024-09-29 - 3.3.0 (no 3.0.\*, 3.1.\*, 3.2.\*) - -### Dynamic Arrays - -- Support for Excel dynamic arrays is added. It is an opt-in feature, so our hope is that there will be no BC breaks, but it is a very large change. Full support is added for Xlsx. It is emulated as Ctrl-Shift-Enter arrays for Ods read and write and Excel2003 and Gnumeric read. Html/Pdf and Csv writers will populate cells on output if they are the result of array formulas. No support is added for Xls or Slk. - -### Added - -- Excel Dynamic Arrays. [Issue #3901](https://github.com/PHPOffice/PhpSpreadsheet/issues/3901) [Issue #3659](https://github.com/PHPOffice/PhpSpreadsheet/issues/3659) [Issue #1834](https://github.com/PHPOffice/PhpSpreadsheet/issues/1834) [PR #3962](https://github.com/PHPOffice/PhpSpreadsheet/pull/3962) -- String Value Binder Allow Setting "Ignore Number Stored as Text". [PR #4141](https://github.com/PHPOffice/PhpSpreadsheet/pull/4141) - -### Changed - -- Xlsx Reader default datatype when none is specified in Xml is changed from string to numeric, which is how Excel treats it. There is expected to be little impact because DefaultValueBinder and AdvancedValueBinder correct mis-identification as string, and StringValueBinder usually expects string. [PR #4139](https://github.com/PHPOffice/PhpSpreadsheet/pull/4139) -- Currency and Accounting Wizards are changed to act like Excel, and a new CurrencyBase Wizard is added for for non-Excel formats. [Issue #4125](https://github.com/PHPOffice/PhpSpreadsheet/issues/4125) [Issue #4124](https://github.com/PHPOffice/PhpSpreadsheet/issues/4124) [PR #4127](https://github.com/PHPOffice/PhpSpreadsheet/pull/4127) -- Images will not be added to spreadsheet if they cannot be validated as images. - -### Deprecated - -- Nothing yet. - -### Removed - -- The following items were deprecated in release 2 and are now removed. -- Writer\Xls\Style\ColorMap (no longer needed). -- Reader\Xml::trySimpleXMLLoadString (should not have been public, no public replacement). -- Calculation\Calculation::_translateFormulaToLocale (use method name translateFormulaToLocale without leading underscore). -- Calculation\Calculation::_translateFormulaToEnglish (use method name translateFormulaToEnglish without leading underscore). - -### Moved - -- Nothing yet. - -### Fixed - -- Several security patches. -- Xls Reader Some Ranges Not Handled Properly. [Issue #1570](https://github.com/PHPOffice/PhpSpreadsheet/issues/1570) [PR #4140](https://github.com/PHPOffice/PhpSpreadsheet/pull/4140) -- Better Handling of legacyDrawing Xml. [Issue #4105](https://github.com/PHPOffice/PhpSpreadsheet/issues/4105) [PR #4122](https://github.com/PHPOffice/PhpSpreadsheet/pull/4122) -- Improve Xlsx Reader Speed. [Issue #3917](https://github.com/PHPOffice/PhpSpreadsheet/issues/3917) [PR #4153](https://github.com/PHPOffice/PhpSpreadsheet/pull/4153) - -## 2024-08-07 - 2.2.2 - -### Added - -- Nothing yet. - -### Changed - -- Nothing yet. - -### Deprecated - -- Nothing yet. - -### Moved - -- Nothing yet. - -### Fixed - -- Html Reader Preserve Unicode Whitespace. [Issue #1284](https://github.com/PHPOffice/PhpSpreadsheet/issues/1284) [PR #4106](https://github.com/PHPOffice/PhpSpreadsheet/pull/4106) -- RATE Function Floating Point Number of Periods. [PR #4107](https://github.com/PHPOffice/PhpSpreadsheet/pull/4107) -- Parameter Name Change Xlsx Writer Workbook. [Issue #4108](https://github.com/PHPOffice/PhpSpreadsheet/issues/4108) [PR #4111](https://github.com/PHPOffice/PhpSpreadsheet/pull/4111) -- New Algorithm for TRUNC, ROUNDUP, ROUNDDOWN. [Issue #4113](https://github.com/PHPOffice/PhpSpreadsheet/issues/4113) [PR #4115](https://github.com/PHPOffice/PhpSpreadsheet/pull/4115) -- Worksheet applyStylesFromArray Retain Active Cell (Excel 16 was having a problem with some files). [Issue #4128](https://github.com/PHPOffice/PhpSpreadsheet/issues/4128) [PR #4132](https://github.com/PHPOffice/PhpSpreadsheet/pull/4132) - -## 2024-07-29 - 2.2.1 - -### Security Fix - -- Prevent XXE when loading files [PR #4119](https://github.com/PHPOffice/PhpSpreadsheet/pull/4119) - -### Fixed - -- Add Sheet may leave Active Sheet uninitialized. [Issue #4112](https://github.com/PHPOffice/PhpSpreadsheet/issues/4112) [PR #4114](https://github.com/PHPOffice/PhpSpreadsheet/pull/4114) -- Reference to Defined Name Specifying Worksheet. [Issue #206](https://github.com/PHPOffice/PhpSpreadsheet/issues/296) [PR #4096](https://github.com/PHPOffice/PhpSpreadsheet/pull/4096) -- Xls Reader Print/Show Gridlines. [Issue #912](https://github.com/PHPOffice/PhpSpreadsheet/issues/912) [PR #4098](https://github.com/PHPOffice/PhpSpreadsheet/pull/4098) -- ODS Reader Allow Omission of Page Settings Tags. [Issue #4099](https://github.com/PHPOffice/PhpSpreadsheet/issues/4099) [PR #4101](https://github.com/PHPOffice/PhpSpreadsheet/pull/4101) - -## 2024-07-24 - 2.2.0 - -### Added - -- Xlsx Reader Optionally Ignore Rows With No Cells. [Issue #3982](https://github.com/PHPOffice/PhpSpreadsheet/issues/3982) [PR #4035](https://github.com/PHPOffice/PhpSpreadsheet/pull/4035) -- Means to change style without affecting current cell/sheet. [PR #4073](https://github.com/PHPOffice/PhpSpreadsheet/pull/4073) -- Option for CSV output file to have varying numbers of columns for each row. [Issue #1415](https://github.com/PHPOffice/PhpSpreadsheet/issues/1415) [PR #4076](https://github.com/PHPOffice/PhpSpreadsheet/pull/4076) - -### Changed - -- On read, Xlsx Reader had been breaking up union ranges into separate individual ranges. It will now try to preserve range as it was read in. [PR #4042](https://github.com/PHPOffice/PhpSpreadsheet/pull/4042) -- Xlsx/Xls spreadsheet calculation and formatting of dates will use base date of spreadsheet even when spreadsheets with different base dates are simultaneously open. [Issue #1036](https://github.com/PHPOffice/PhpSpreadsheet/issues/1036) [Issue #1635](https://github.com/PHPOffice/PhpSpreadsheet/issues/1635) [PR #4071](https://github.com/PHPOffice/PhpSpreadsheet/pull/4071) - -### Deprecated - -- Writer\Xls\Style\ColorMap is no longer needed. - -### Moved - -- Nothing - -### Fixed - -- Incorrect Reader CSV with BOM. [Issue #4028](https://github.com/PHPOffice/PhpSpreadsheet/issues/4028) [PR #4029](https://github.com/PHPOffice/PhpSpreadsheet/pull/4029) -- POWER Null/Bool Args. [PR #4031](https://github.com/PHPOffice/PhpSpreadsheet/pull/4031) -- Do Not Output Alignment and Protection for Conditional Format. [Issue #4025](https://github.com/PHPOffice/PhpSpreadsheet/issues/4025) [PR #4027](https://github.com/PHPOffice/PhpSpreadsheet/pull/4027) -- Conditional Color Scale Improvements. [Issue #4049](https://github.com/PHPOffice/PhpSpreadsheet/issues/4049) [PR #4050](https://github.com/PHPOffice/PhpSpreadsheet/pull/4050) -- Mpdf and Tcpdf Borders on Merged Cells. [Issue #3557](https://github.com/PHPOffice/PhpSpreadsheet/issues/3557) [PR #4047](https://github.com/PHPOffice/PhpSpreadsheet/pull/4047) -- Xls Conditional Format Improvements. [PR #4030](https://github.com/PHPOffice/PhpSpreadsheet/pull/4030) [PR #4033](https://github.com/PHPOffice/PhpSpreadsheet/pull/4033) -- Conditional Range Unions and Intersections [Issue #4039](https://github.com/PHPOffice/PhpSpreadsheet/issues/4039) [PR #4042](https://github.com/PHPOffice/PhpSpreadsheet/pull/4042) -- Ods comments with newlines. [Issue #4081](https://github.com/PHPOffice/PhpSpreadsheet/issues/4081) [PR #4086](https://github.com/PHPOffice/PhpSpreadsheet/pull/4086) -- Propagate errors in Text functions. [Issue #2581](https://github.com/PHPOffice/PhpSpreadsheet/issues/2581) [PR #4080](https://github.com/PHPOffice/PhpSpreadsheet/pull/4080) -- Csv Reader allow use of html mimetype. [Issue #4036](https://github.com/PHPOffice/PhpSpreadsheet/issues/4036) [PR #4040](https://github.com/PHPOffice/PhpSpreadsheet/pull/4040) -- Problem rendering line chart with missing plot label. [PR #4074](https://github.com/PHPOffice/PhpSpreadsheet/pull/4074) -- More RTL in Xlsx/Html Comments [Issue #4004](https://github.com/PHPOffice/PhpSpreadsheet/issues/4004) [PR #4065](https://github.com/PHPOffice/PhpSpreadsheet/pull/4065) -- Empty String in sharedStrings. [Issue #4063](https://github.com/PHPOffice/PhpSpreadsheet/issues/4063) [PR #4064](https://github.com/PHPOffice/PhpSpreadsheet/pull/4064) -- Xlsx Writer RichText and TYPE_STRING. [Issue #476](https://github.com/PHPOffice/PhpSpreadsheet/issues/476) [PR #4094](https://github.com/PHPOffice/PhpSpreadsheet/pull/4094) -- Ods boolean data. [Issue #460](https://github.com/PHPOffice/PhpSpreadsheet/issues/460) [PR #4093](https://github.com/PHPOffice/PhpSpreadsheet/pull/4093) -- Html Writer Minor Fixes. [PR #4089](https://github.com/PHPOffice/PhpSpreadsheet/pull/4089) -- Changes to INDEX function. [Issue #64](https://github.com/PHPOffice/PhpSpreadsheet/issues/64) [PR #4088](https://github.com/PHPOffice/PhpSpreadsheet/pull/4088) -- Ods Reader and Whitespace Text Nodes. [Issue #804](https://github.com/PHPOffice/PhpSpreadsheet/issues/804) [PR #4087](https://github.com/PHPOffice/PhpSpreadsheet/pull/4087) -- Ods Xml Reader and Whitespace Text Nodes. [Issue #804](https://github.com/PHPOffice/PhpSpreadsheet/issues/804) [PR #4087](https://github.com/PHPOffice/PhpSpreadsheet/pull/4087) -- Treat invalid formulas as strings. [Issue #1310](https://github.com/PHPOffice/PhpSpreadsheet/issues/1310) [PR #4073](https://github.com/PHPOffice/PhpSpreadsheet/pull/4073) - -## 2024-05-11 - 2.1.0 - -### MINOR BREAKING CHANGE - -- Writing of cell comments to Html will now sanitize all Html tags within the comment, so the tags will be rendered as plaintext and have no other effects when rendered. Styling can be achieved by using the Font property of of the TextRuns which make up the comment, as is already the cases for Xlsx. [PR #3957](https://github.com/PHPOffice/PhpSpreadsheet/pull/3957) - -### Added - -- Default Style Alignment Property (workaround for bug in non-Excel spreadsheet apps) [Issue #3918](https://github.com/PHPOffice/PhpSpreadsheet/issues/3918) [PR #3924](https://github.com/PHPOffice/PhpSpreadsheet/pull/3924) -- Additional Support for Date/Time Styles [PR #3939](https://github.com/PHPOffice/PhpSpreadsheet/pull/3939) - -### Changed - -- Nothing - -### Deprecated - -- Reader/Xml trySimpleXMLLoadString should not have had public visibility, and will be removed. - -### Removed - -- Nothing - -### Fixed - -- IF Empty Arguments. [Issue #3875](https://github.com/PHPOffice/PhpSpreadsheet/issues/3875) [Issue #2146](https://github.com/PHPOffice/PhpSpreadsheet/issues/2146) [PR #3879](https://github.com/PHPOffice/PhpSpreadsheet/pull/3879) -- Changes to floating point in Php8.4. [Issue #3896](https://github.com/PHPOffice/PhpSpreadsheet/issues/3896) [PR #3897](https://github.com/PHPOffice/PhpSpreadsheet/pull/3897) -- Handling User-supplied Decimal and Thousands Separators. [Issue #3900](https://github.com/PHPOffice/PhpSpreadsheet/issues/3900) [PR #3903](https://github.com/PHPOffice/PhpSpreadsheet/pull/3903) -- Improve Performance of CSV Writer. [Issue #3904](https://github.com/PHPOffice/PhpSpreadsheet/issues/3904) [PR #3906](https://github.com/PHPOffice/PhpSpreadsheet/pull/3906) -- Fix issue with prepending zero in percentage [Issue #3920](https://github.com/PHPOffice/PhpSpreadsheet/issues/3920) [PR #3921](https://github.com/PHPOffice/PhpSpreadsheet/pull/3921) -- Incorrect SUMPRODUCT Calculation [Issue #3909](https://github.com/PHPOffice/PhpSpreadsheet/issues/3909) [PR #3916](https://github.com/PHPOffice/PhpSpreadsheet/pull/3916) -- Formula Misidentifying Text as Cell After Insertion/Deletion [Issue #3907](https://github.com/PHPOffice/PhpSpreadsheet/issues/3907) [PR #3915](https://github.com/PHPOffice/PhpSpreadsheet/pull/3915) -- Unexpected Absolute Address in Xlsx Rels [Issue #3730](https://github.com/PHPOffice/PhpSpreadsheet/issues/3730) [PR #3923](https://github.com/PHPOffice/PhpSpreadsheet/pull/3923) -- Unallocated Cells Affected by Column/Row Insert/Delete [Issue #3933](https://github.com/PHPOffice/PhpSpreadsheet/issues/3933) [PR #3940](https://github.com/PHPOffice/PhpSpreadsheet/pull/3940) -- Invalid Builtin Defined Name in Xls Reader [Issue #3935](https://github.com/PHPOffice/PhpSpreadsheet/issues/3935) [PR #3942](https://github.com/PHPOffice/PhpSpreadsheet/pull/3942) -- Hidden Rows and Columns Tcpdf/Mpdf [PR #3945](https://github.com/PHPOffice/PhpSpreadsheet/pull/3945) -- RTL Text Alignment in Xlsx Comments [Issue #4004](https://github.com/PHPOffice/PhpSpreadsheet/issues/4004) [PR #4006](https://github.com/PHPOffice/PhpSpreadsheet/pull/4006) -- Protect Sheet But Allow Sort [Issue #3951](https://github.com/PHPOffice/PhpSpreadsheet/issues/3951) [PR #3956](https://github.com/PHPOffice/PhpSpreadsheet/pull/3956) -- Default Value for Conditional::$text [PR #3946](https://github.com/PHPOffice/PhpSpreadsheet/pull/3946) -- Table Filter Buttons [Issue #3988](https://github.com/PHPOffice/PhpSpreadsheet/issues/3988) [PR #3992](https://github.com/PHPOffice/PhpSpreadsheet/pull/3992) -- Improvements to Xml Reader [Issue #3999](https://github.com/PHPOffice/PhpSpreadsheet/issues/3999) [Issue #4000](https://github.com/PHPOffice/PhpSpreadsheet/issues/4000) [Issue #4001](https://github.com/PHPOffice/PhpSpreadsheet/issues/4001) [Issue #4002](https://github.com/PHPOffice/PhpSpreadsheet/issues/4002) [PR #4003](https://github.com/PHPOffice/PhpSpreadsheet/pull/4003) [PR #4007](https://github.com/PHPOffice/PhpSpreadsheet/pull/4007) -- Html Reader non-UTF8 [Issue #3995](https://github.com/PHPOffice/PhpSpreadsheet/issues/3995) [Issue #866](https://github.com/PHPOffice/PhpSpreadsheet/issues/866) [Issue #1681](https://github.com/PHPOffice/PhpSpreadsheet/issues/1681) [PR #4019](https://github.com/PHPOffice/PhpSpreadsheet/pull/4019) - -## 2.0.0 - 2024-01-04 - -### BREAKING CHANGE - -- Typing was strengthened by leveraging native typing. This should not change any behavior. However, if you implement - any interfaces or inherit from any classes, you will need to adapt your typing accordingly. If you use static analysis - tools such as PHPStan or Psalm, new errors might be found. If you find actual bugs because of the new typing, please - open a PR that fixes it with a **detailed** explanation of the reason. We'll try to merge and release typing-related - fixes quickly in the coming days. [PR #3718](https://github.com/PHPOffice/PhpSpreadsheet/pull/3718) -- All deprecated things have been removed, for details, see [816b91d0b4](https://github.com/PHPOffice/PhpSpreadsheet/commit/816b91d0b4a0c7285a9e3fc88c58f7730d922044) - -### Added - -- Split screens (Xlsx and Xml only, not 100% complete). [Issue #3601](https://github.com/PHPOffice/PhpSpreadsheet/issues/3601) [PR #3622](https://github.com/PHPOffice/PhpSpreadsheet/pull/3622) -- Permit Meta Viewport in Html. [Issue #3565](https://github.com/PHPOffice/PhpSpreadsheet/issues/3565) [PR #3623](https://github.com/PHPOffice/PhpSpreadsheet/pull/3623) -- Hyperlink support for Ods. [Issue #3660](https://github.com/PHPOffice/PhpSpreadsheet/issues/3660) [PR #3669](https://github.com/PHPOffice/PhpSpreadsheet/pull/3669) -- ListWorksheetInfo/Names for Html/Csv/Slk. [Issue #3706](https://github.com/PHPOffice/PhpSpreadsheet/issues/3706) [PR #3709](https://github.com/PHPOffice/PhpSpreadsheet/pull/3709) -- Methods to determine if cell is actually locked, or hidden on formula bar. [PR #3722](https://github.com/PHPOffice/PhpSpreadsheet/pull/3722) -- Add iterateOnlyExistingCells to Constructors. [Issue #3721](https://github.com/PHPOffice/PhpSpreadsheet/issues/3721) [PR #3727](https://github.com/PHPOffice/PhpSpreadsheet/pull/3727) -- Support for Conditional Formatting Color Scale. [PR #3738](https://github.com/PHPOffice/PhpSpreadsheet/pull/3738) -- Support Additional Tags in Helper/Html. [Issue #3751](https://github.com/PHPOffice/PhpSpreadsheet/issues/3751) [PR #3752](https://github.com/PHPOffice/PhpSpreadsheet/pull/3752) -- Writer ODS : Write Border Style for cells [Issue #3690](https://github.com/PHPOffice/PhpSpreadsheet/issues/3690) [PR #3693](https://github.com/PHPOffice/PhpSpreadsheet/pull/3693) -- Sheet Background Images [Issue #1649](https://github.com/PHPOffice/PhpSpreadsheet/issues/1649) [PR #3795](https://github.com/PHPOffice/PhpSpreadsheet/pull/3795) -- Check if Coordinate is Inside Range [PR #3779](https://github.com/PHPOffice/PhpSpreadsheet/pull/3779) -- Flipping Images [Issue #731](https://github.com/PHPOffice/PhpSpreadsheet/issues/731) [PR #3801](https://github.com/PHPOffice/PhpSpreadsheet/pull/3801) -- Chart Dynamic Title and Font Properties [Issue #3797](https://github.com/PHPOffice/PhpSpreadsheet/issues/3797) [PR #3800](https://github.com/PHPOffice/PhpSpreadsheet/pull/3800) -- Chart Axis Display Units and Logarithmic Scale. [Issue #3833](https://github.com/PHPOffice/PhpSpreadsheet/issues/3833) [PR #3836](https://github.com/PHPOffice/PhpSpreadsheet/pull/3836) -- Partial Support of Fill Handles. [Discussion #3847](https://github.com/PHPOffice/PhpSpreadsheet/discussions/3847) [PR #3855](https://github.com/PHPOffice/PhpSpreadsheet/pull/3855) - -### Changed - -- **Drop support for PHP 7.4**, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support [PR #3713](https://github.com/PHPOffice/PhpSpreadsheet/pull/3713) -- RLM Added to NumberFormatter Currency. This happens depending on release of ICU which Php is using (it does not yet happen with any official release). PhpSpreadsheet will continue to use the value returned by Php, but a method is added to keep the result unchanged from release to release. [Issue #3571](https://github.com/PHPOffice/PhpSpreadsheet/issues/3571) [PR #3640](https://github.com/PHPOffice/PhpSpreadsheet/pull/3640) -- `toFormattedString` will now always return a string. This was introduced with 1.28.0, but was not properly documented at the time. This can affect the results of `toArray`, `namedRangeToArray`, and `rangeToArray`. [PR #3304](https://github.com/PHPOffice/PhpSpreadsheet/pull/3304) -- Value of constants FORMAT_CURRENCY_EUR and FORMAT_CURRENCY_USD was changed in 1.28.0, but was not properly documented at the time. [Issue #3577](https://github.com/PHPOffice/PhpSpreadsheet/issues/3577) -- Html Writer will attempt to use Chart coordinates to determine image size. [Issue #3783](https://github.com/PHPOffice/PhpSpreadsheet/issues/3783) [PR #3787](https://github.com/PHPOffice/PhpSpreadsheet/pull/3787) - -### Deprecated - -- Functions `_translateFormulaToLocale` and `_translateFormulaEnglish` are replaced by versions without leading underscore. [PR #3828](https://github.com/PHPOffice/PhpSpreadsheet/pull/3828) - -### Removed - -- Nothing - -### Fixed - -- Take advantage of mitoteam/jpgraph Extended mode to enable rendering of more graphs. [PR #3603](https://github.com/PHPOffice/PhpSpreadsheet/pull/3603) -- Column widths, especially for ODS. [Issue #3609](https://github.com/PHPOffice/PhpSpreadsheet/issues/3609) [PR #3610](https://github.com/PHPOffice/PhpSpreadsheet/pull/3610) -- Avoid NULL in String Function call (partial solution). [Issue #3613](https://github.com/PHPOffice/PhpSpreadsheet/issues/3613) [PR #3617](https://github.com/PHPOffice/PhpSpreadsheet/pull/3617) -- Preserve transparency in Memory Drawing. [Issue #3624](https://github.com/PHPOffice/PhpSpreadsheet/issues/3624) [PR #3627](https://github.com/PHPOffice/PhpSpreadsheet/pull/3627) -- Customizable padding for Exact Column Width. [Issue #3626](https://github.com/PHPOffice/PhpSpreadsheet/issues/3626) [PR #3628](https://github.com/PHPOffice/PhpSpreadsheet/pull/3628) -- Ensure ROW function returns int (problem exposed in unreleased Php). [PR #3641](https://github.com/PHPOffice/PhpSpreadsheet/pull/3641) -- Minor changes to Mpdf and Html Writers. [PR #3645](https://github.com/PHPOffice/PhpSpreadsheet/pull/3645) -- Xlsx Reader Namespacing for Tables, Autofilters. [Issue #3665](https://github.com/PHPOffice/PhpSpreadsheet/issues/3665) [PR #3668](https://github.com/PHPOffice/PhpSpreadsheet/pull/3668) -- Read Code Page for Xls ListWorksheetInfo/Names BIFF5. [Issue #3671](https://github.com/PHPOffice/PhpSpreadsheet/issues/3671) [PR #3672](https://github.com/PHPOffice/PhpSpreadsheet/pull/3672) -- Read Data from Table on Different Sheet. [Issue #3635](https://github.com/PHPOffice/PhpSpreadsheet/issues/3635) [PR #3659](https://github.com/PHPOffice/PhpSpreadsheet/pull/3659) -- Html Writer Styles Using Inline Css. [Issue #3678](https://github.com/PHPOffice/PhpSpreadsheet/issues/3678) [PR #3680](https://github.com/PHPOffice/PhpSpreadsheet/pull/3680) -- Xlsx Read Ignoring Some Comments. [Issue #3654](https://github.com/PHPOffice/PhpSpreadsheet/issues/3654) [PR #3655](https://github.com/PHPOffice/PhpSpreadsheet/pull/3655) -- Fractional Seconds in Date/Time Values. [PR #3677](https://github.com/PHPOffice/PhpSpreadsheet/pull/3677) -- SetCalculatedValue Avoid Casting String to Numeric. [Issue #3658](https://github.com/PHPOffice/PhpSpreadsheet/issues/3658) [PR #3685](https://github.com/PHPOffice/PhpSpreadsheet/pull/3685) -- Several Problems in a Very Complicated Spreadsheet. [Issue #3679](https://github.com/PHPOffice/PhpSpreadsheet/issues/3679) [PR #3681](https://github.com/PHPOffice/PhpSpreadsheet/pull/3681) -- Inconsistent String Handling for Sum Functions. [Issue #3652](https://github.com/PHPOffice/PhpSpreadsheet/issues/3652) [PR #3653](https://github.com/PHPOffice/PhpSpreadsheet/pull/3653) -- Recomputation of Relative Addresses in Defined Names. [Issue #3661](https://github.com/PHPOffice/PhpSpreadsheet/issues/3661) [PR #3673](https://github.com/PHPOffice/PhpSpreadsheet/pull/3673) -- Writer Xls Characters Outside BMP (emojis). [Issue #642](https://github.com/PHPOffice/PhpSpreadsheet/issues/642) [PR #3696](https://github.com/PHPOffice/PhpSpreadsheet/pull/3696) -- Xlsx Reader Improve Handling of Row and Column Styles. [Issue #3533](https://github.com/PHPOffice/PhpSpreadsheet/issues/3533) [Issue #3534](https://github.com/PHPOffice/PhpSpreadsheet/issues/3534) [PR #3688](https://github.com/PHPOffice/PhpSpreadsheet/pull/3688) -- Avoid Allocating RowDimension Unneccesarily. [PR #3686](https://github.com/PHPOffice/PhpSpreadsheet/pull/3686) -- Use Column Style when Row Dimension Exists Without Style. [Issue #3534](https://github.com/PHPOffice/PhpSpreadsheet/issues/3534) [PR #3688](https://github.com/PHPOffice/PhpSpreadsheet/pull/3688) -- Inconsistency Between Cell Data and Explicitly Declared Type. [Issue #3711](https://github.com/PHPOffice/PhpSpreadsheet/issues/3711) [PR #3715](https://github.com/PHPOffice/PhpSpreadsheet/pull/3715) -- Unexpected Namespacing in rels File. [Issue #3720](https://github.com/PHPOffice/PhpSpreadsheet/issues/3720) [PR #3722](https://github.com/PHPOffice/PhpSpreadsheet/pull/3722) -- Break Some Circular References. [PR #3716](https://github.com/PHPOffice/PhpSpreadsheet/pull/3716) [PR #3707](https://github.com/PHPOffice/PhpSpreadsheet/pull/3707) -- Missing Font Index in Some Xls. [PR #3734](https://github.com/PHPOffice/PhpSpreadsheet/pull/3734) -- Load Tables even with READ_DATA_ONLY. [PR #3726](https://github.com/PHPOffice/PhpSpreadsheet/pull/3726) -- Theme File Missing but Referenced in Spreadsheet. [Issue #3770](https://github.com/PHPOffice/PhpSpreadsheet/issues/3770) [PR #3772](https://github.com/PHPOffice/PhpSpreadsheet/pull/3772) -- Slk Shared Formulas. [Issue #2267](https://github.com/PHPOffice/PhpSpreadsheet/issues/2267) [PR #3776](https://github.com/PHPOffice/PhpSpreadsheet/pull/3776) -- Html omitting some charts. [Issue #3767](https://github.com/PHPOffice/PhpSpreadsheet/issues/3767) [PR #3771](https://github.com/PHPOffice/PhpSpreadsheet/pull/3771) -- Case Insensitive Comparison for Sheet Names [PR #3791](https://github.com/PHPOffice/PhpSpreadsheet/pull/3791) -- Performance improvement for Xlsx Reader. [Issue #3683](https://github.com/PHPOffice/PhpSpreadsheet/issues/3683) [PR #3810](https://github.com/PHPOffice/PhpSpreadsheet/pull/3810) -- Prevent loop in Shared/File. [Issue #3807](https://github.com/PHPOffice/PhpSpreadsheet/issues/3807) [PR #3809](https://github.com/PHPOffice/PhpSpreadsheet/pull/3809) -- Consistent handling of decimal/thousands separators between StringHelper and Php setlocale. [Issue #3811](https://github.com/PHPOffice/PhpSpreadsheet/issues/3811) [PR #3815](https://github.com/PHPOffice/PhpSpreadsheet/pull/3815) -- Clone worksheet with tables or charts. [Issue #3820](https://github.com/PHPOffice/PhpSpreadsheet/issues/3820) [PR #3821](https://github.com/PHPOffice/PhpSpreadsheet/pull/3821) -- COUNTIFS Does Not Require xlfn. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3827](https://github.com/PHPOffice/PhpSpreadsheet/pull/3827) -- Strip `xlfn.` and `xlws.` from Formula Translations. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3828](https://github.com/PHPOffice/PhpSpreadsheet/pull/3828) -- Recurse directories searching for font file. [Issue #2809](https://github.com/PHPOffice/PhpSpreadsheet/issues/2809) [PR #3830](https://github.com/PHPOffice/PhpSpreadsheet/pull/3830) -- Reduce memory consumption of Worksheet::rangeToArray() when many empty rows are read. [Issue #3814](https://github.com/PHPOffice/PhpSpreadsheet/issues/3814) [PR #3834](https://github.com/PHPOffice/PhpSpreadsheet/pull/3834) -- Reduce time used by Worksheet::rangeToArray() when many empty rows are read. [PR #3839](https://github.com/PHPOffice/PhpSpreadsheet/pull/3839) -- Html Reader Tolerate Invalid Sheet Title. [PR #3845](https://github.com/PHPOffice/PhpSpreadsheet/pull/3845) -- Do not include unparsed drawings when new drawing added. [Issue #3843](https://github.com/PHPOffice/PhpSpreadsheet/issues/3843) [PR #3846](https://github.com/PHPOffice/PhpSpreadsheet/pull/3846) -- Do not include unparsed drawings when new drawing added. [Issue #3861](https://github.com/PHPOffice/PhpSpreadsheet/issues/3861) [PR #3862](https://github.com/PHPOffice/PhpSpreadsheet/pull/3862) -- Excel omits `between` operator for data validation. [Issue #3863](https://github.com/PHPOffice/PhpSpreadsheet/issues/3863) [PR #3865](https://github.com/PHPOffice/PhpSpreadsheet/pull/3865) -- Use less space when inserting rows and columns. [Issue #3687](https://github.com/PHPOffice/PhpSpreadsheet/issues/3687) [PR #3856](https://github.com/PHPOffice/PhpSpreadsheet/pull/3856) -- Excel inconsistent handling of MIN/MAX/MINA/MAXA. [Issue #3866](https://github.com/PHPOffice/PhpSpreadsheet/issues/3866) [PR #3868](https://github.com/PHPOffice/PhpSpreadsheet/pull/3868) - -## 1.29.0 - 2023-06-15 - -### Added - -- Wizards for defining Number Format masks for Dates and Times, including Durations/Intervals. [PR #3458](https://github.com/PHPOffice/PhpSpreadsheet/pull/3458) -- Specify data type in html tags. [Issue #3444](https://github.com/PHPOffice/PhpSpreadsheet/issues/3444) [PR #3445](https://github.com/PHPOffice/PhpSpreadsheet/pull/3445) -- Provide option to ignore hidden rows/columns in `toArray()` methods. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) -- Font/Effects/Theme support for Chart Data Labels and Axis. [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) -- Font Themes support. [PR #3486](https://github.com/PHPOffice/PhpSpreadsheet/pull/3486) -- Ability to Ignore Cell Errors in Excel. [Issue #1141](https://github.com/PHPOffice/PhpSpreadsheet/issues/1141) [PR #3508](https://github.com/PHPOffice/PhpSpreadsheet/pull/3508) -- Unzipped Gnumeric file [PR #3591](https://github.com/PHPOffice/PhpSpreadsheet/pull/3591) - -### Changed - -- Xlsx Color schemes read in will be written out (previously Excel 2007-2010 Color scheme was always written); manipulation of those schemes before write, including restoring prior behavior, is provided [PR #3476](https://github.com/PHPOffice/PhpSpreadsheet/pull/3476) -- Memory and speed optimisations for Read Filters with Xlsx Files and Shared Formulae. [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) -- Allow `CellRange` and `CellAddress` objects for the `range` argument in the `rangeToArray()` method. [PR #3494](https://github.com/PHPOffice/PhpSpreadsheet/pull/3494) -- Stock charts will now read and reproduce `upDownBars` and subsidiary tags; these were previously ignored on read and hard-coded on write. [PR #3515](https://github.com/PHPOffice/PhpSpreadsheet/pull/3515) - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Updates Cell formula absolute ranges/references, and Defined Name absolute ranges/references when inserting/deleting rows/columns. [Issue #3368](https://github.com/PHPOffice/PhpSpreadsheet/issues/3368) [PR #3402](https://github.com/PHPOffice/PhpSpreadsheet/pull/3402) -- EOMONTH() and EDATE() Functions should round date value before evaluation. [Issue #3436](https://github.com/PHPOffice/PhpSpreadsheet/issues/3436) [PR #3437](https://github.com/PHPOffice/PhpSpreadsheet/pull/3437) -- NETWORKDAYS function erroneously being converted to NETWORK_xlfn.DAYS in Xlsx Writer. [Issue #3461](https://github.com/PHPOffice/PhpSpreadsheet/issues/3461) [PR #3463](https://github.com/PHPOffice/PhpSpreadsheet/pull/3463) -- Getting a style for a CellAddress instance fails if the worksheet is set in the CellAddress instance. [Issue #3439](https://github.com/PHPOffice/PhpSpreadsheet/issues/3439) [PR #3469](https://github.com/PHPOffice/PhpSpreadsheet/pull/3469) -- Shared Formulae outside the filter range when reading with a filter are not always being identified. [Issue #3473](https://github.com/PHPOffice/PhpSpreadsheet/issues/3473) [PR #3474](https://github.com/PHPOffice/PhpSpreadsheet/pull/3474) -- Xls Reader Conditional Styles. [PR #3400](https://github.com/PHPOffice/PhpSpreadsheet/pull/3400) -- Allow use of # and 0 digit placeholders in fraction masks. [PR #3401](https://github.com/PHPOffice/PhpSpreadsheet/pull/3401) -- Modify Date/Time check in the NumberFormatter for decimal/fractional times. [PR #3413](https://github.com/PHPOffice/PhpSpreadsheet/pull/3413) -- Misplaced Xml Writing Chart Label FillColor. [Issue #3397](https://github.com/PHPOffice/PhpSpreadsheet/issues/3397) [PR #3404](https://github.com/PHPOffice/PhpSpreadsheet/pull/3404) -- TEXT function ignores Time in DateTimeStamp. [Issue #3409](https://github.com/PHPOffice/PhpSpreadsheet/issues/3409) [PR #3411](https://github.com/PHPOffice/PhpSpreadsheet/pull/3411) -- Xlsx Column Autosize Approximate for CJK. [Issue #3405](https://github.com/PHPOffice/PhpSpreadsheet/issues/3405) [PR #3416](https://github.com/PHPOffice/PhpSpreadsheet/pull/3416) -- Correct Xlsx Parsing of quotePrefix="0". [Issue #3435](https://github.com/PHPOffice/PhpSpreadsheet/issues/3435) [PR #3438](https://github.com/PHPOffice/PhpSpreadsheet/pull/3438) -- More Display Options for Chart Axis and Legend. [Issue #3414](https://github.com/PHPOffice/PhpSpreadsheet/issues/3414) [PR #3434](https://github.com/PHPOffice/PhpSpreadsheet/pull/3434) -- Apply strict type checking to Complex suffix. [PR #3452](https://github.com/PHPOffice/PhpSpreadsheet/pull/3452) -- Incorrect Font Color Read Xlsx Rich Text Indexed Color Custom Palette. [Issue #3464](https://github.com/PHPOffice/PhpSpreadsheet/issues/3464) [PR #3465](https://github.com/PHPOffice/PhpSpreadsheet/pull/3465) -- Xlsx Writer Honor Alignment in Default Font. [Issue #3443](https://github.com/PHPOffice/PhpSpreadsheet/issues/3443) [PR #3459](https://github.com/PHPOffice/PhpSpreadsheet/pull/3459) -- Support Border for Charts. [PR #3462](https://github.com/PHPOffice/PhpSpreadsheet/pull/3462) -- Error in "this row" structured reference calculation (cached result from first row when using a range) [Issue #3504](https://github.com/PHPOffice/PhpSpreadsheet/issues/3504) [PR #3505](https://github.com/PHPOffice/PhpSpreadsheet/pull/3505) -- Allow colour palette index references in Number Format masks [Issue #3511](https://github.com/PHPOffice/PhpSpreadsheet/issues/3511) [PR #3512](https://github.com/PHPOffice/PhpSpreadsheet/pull/3512) -- Xlsx Reader formula with quotePrefix [Issue #3495](https://github.com/PHPOffice/PhpSpreadsheet/issues/3495) [PR #3497](https://github.com/PHPOffice/PhpSpreadsheet/pull/3497) -- Handle REF error as part of range [Issue #3453](https://github.com/PHPOffice/PhpSpreadsheet/issues/3453) [PR #3467](https://github.com/PHPOffice/PhpSpreadsheet/pull/3467) -- Handle Absolute Pathnames in Rels File [Issue #3553](https://github.com/PHPOffice/PhpSpreadsheet/issues/3553) [PR #3554](https://github.com/PHPOffice/PhpSpreadsheet/pull/3554) -- Return Page Breaks in Order [Issue #3552](https://github.com/PHPOffice/PhpSpreadsheet/issues/3552) [PR #3555](https://github.com/PHPOffice/PhpSpreadsheet/pull/3555) -- Add position attribute for MemoryDrawing in Html [Issue #3529](https://github.com/PHPOffice/PhpSpreadsheet/issues/3529 [PR #3535](https://github.com/PHPOffice/PhpSpreadsheet/pull/3535) -- Allow Index_number as Array for VLOOKUP/HLOOKUP [Issue #3561](https://github.com/PHPOffice/PhpSpreadsheet/issues/3561 [PR #3570](https://github.com/PHPOffice/PhpSpreadsheet/pull/3570) -- Add Unsupported Options in Xml Spreadsheet [Issue #3566](https://github.com/PHPOffice/PhpSpreadsheet/issues/3566 [Issue #3568](https://github.com/PHPOffice/PhpSpreadsheet/issues/3568 [Issue #3569](https://github.com/PHPOffice/PhpSpreadsheet/issues/3569 [PR #3567](https://github.com/PHPOffice/PhpSpreadsheet/pull/3567) -- Changes to NUMBERVALUE, VALUE, DATEVALUE, TIMEVALUE [Issue #3574](https://github.com/PHPOffice/PhpSpreadsheet/issues/3574 [PR #3575](https://github.com/PHPOffice/PhpSpreadsheet/pull/3575) -- Redo calculation of color tinting [Issue #3550](https://github.com/PHPOffice/PhpSpreadsheet/issues/3550) [PR #3580](https://github.com/PHPOffice/PhpSpreadsheet/pull/3580) -- Accommodate Slash with preg_quote [PR #3582](https://github.com/PHPOffice/PhpSpreadsheet/pull/3582) [PR #3583](https://github.com/PHPOffice/PhpSpreadsheet/pull/3583) [PR #3584](https://github.com/PHPOffice/PhpSpreadsheet/pull/3584) -- HyperlinkBase Property and Html Handling of Properties [Issue #3573](https://github.com/PHPOffice/PhpSpreadsheet/issues/3573) [PR #3589](https://github.com/PHPOffice/PhpSpreadsheet/pull/3589) -- Improvements for Data Validation [Issue #3592](https://github.com/PHPOffice/PhpSpreadsheet/issues/3592) [Issue #3594](https://github.com/PHPOffice/PhpSpreadsheet/issues/3594) [PR #3605](https://github.com/PHPOffice/PhpSpreadsheet/pull/3605) - -## 1.28.0 - 2023-02-25 - -### Added - -- Support for configuring a Chart Title's overlay [PR #3325](https://github.com/PHPOffice/PhpSpreadsheet/pull/3325) -- Wizards for defining Number Format masks for Numbers, Percentages, Scientific, Currency and Accounting [PR #3334](https://github.com/PHPOffice/PhpSpreadsheet/pull/3334) -- Support for fixed value divisor in fractional Number Format Masks [PR #3339](https://github.com/PHPOffice/PhpSpreadsheet/pull/3339) -- Allow More Fonts/Fontnames for Exact Width Calculation [PR #3326](https://github.com/PHPOffice/PhpSpreadsheet/pull/3326) [Issue #3190](https://github.com/PHPOffice/PhpSpreadsheet/issues/3190) -- Allow override of the Value Binder when setting a Cell value [PR #3361](https://github.com/PHPOffice/PhpSpreadsheet/pull/3361) - -### Changed - -- Improved handling for @ placeholder in Number Format Masks [PR #3344](https://github.com/PHPOffice/PhpSpreadsheet/pull/3344) -- Improved handling for ? placeholder in Number Format Masks [PR #3394](https://github.com/PHPOffice/PhpSpreadsheet/pull/3394) -- Improved support for locale settings and currency codes when matching formatted strings to numerics in the Calculation Engine [PR #3373](https://github.com/PHPOffice/PhpSpreadsheet/pull/3373) and [PR #3374](https://github.com/PHPOffice/PhpSpreadsheet/pull/3374) -- Improved support for locale settings and matching in the Advanced Value Binder [PR #3376](https://github.com/PHPOffice/PhpSpreadsheet/pull/3376) -- `toFormattedString` will now always return a string. This can affect the results of `toArray`, `namedRangeToArray`, and `rangeToArray`. [PR #3304](https://github.com/PHPOffice/PhpSpreadsheet/pull/3304) -- Value of constants FORMAT_CURRENCY_EUR and FORMAT_CURRENCY_USD is changed. [Issue #3577](https://github.com/PHPOffice/PhpSpreadsheet/issues/3577) [PR #3377](https://github.com/PHPOffice/PhpSpreadsheet/pull/3377) - -### Deprecated - -- Rationalisation of Pre-defined Currency Format Masks [PR #3377](https://github.com/PHPOffice/PhpSpreadsheet/pull/3377) - -### Removed - -- Nothing - -### Fixed - -- Calculation Engine doesn't evaluate Defined Name when default cell A1 is quote-prefixed [Issue #3335](https://github.com/PHPOffice/PhpSpreadsheet/issues/3335) [PR #3336](https://github.com/PHPOffice/PhpSpreadsheet/pull/3336) -- XLSX Writer - Array Formulas do not include function prefix [Issue #3337](https://github.com/PHPOffice/PhpSpreadsheet/issues/3337) [PR #3338](https://github.com/PHPOffice/PhpSpreadsheet/pull/3338) -- Permit Max Column for Row Breaks [Issue #3143](https://github.com/PHPOffice/PhpSpreadsheet/issues/3143) [PR #3345](https://github.com/PHPOffice/PhpSpreadsheet/pull/3345) -- AutoSize Columns should allow for dropdown icon when AutoFilter is for a Table [Issue #3356](https://github.com/PHPOffice/PhpSpreadsheet/issues/3356) [PR #3358](https://github.com/PHPOffice/PhpSpreadsheet/pull/3358) and for Center Alignment of Headers [Issue #3395](https://github.com/PHPOffice/PhpSpreadsheet/issues/3395) [PR #3399](https://github.com/PHPOffice/PhpSpreadsheet/pull/3399) -- Decimal Precision for Scientific Number Format Mask [Issue #3381](https://github.com/PHPOffice/PhpSpreadsheet/issues/3381) [PR #3382](https://github.com/PHPOffice/PhpSpreadsheet/pull/3382) -- Xls Writer Parser Handle Boolean Literals as Function Arguments [Issue #3369](https://github.com/PHPOffice/PhpSpreadsheet/issues/3369) [PR #3391](https://github.com/PHPOffice/PhpSpreadsheet/pull/3391) -- Conditional Formatting Improvements for Xlsx [Issue #3370](https://github.com/PHPOffice/PhpSpreadsheet/issues/3370) [Issue #3202](https://github.com/PHPOffice/PhpSpreadsheet/issues/3302) [PR #3372](https://github.com/PHPOffice/PhpSpreadsheet/pull/3372) -- Coerce Bool to Int for Mathematical Operations on Arrays [Issue #3389](https://github.com/PHPOffice/PhpSpreadsheet/issues/3389) [Issue #3396](https://github.com/PHPOffice/PhpSpreadsheet/issues/3396) [PR #3392](https://github.com/PHPOffice/PhpSpreadsheet/pull/3392) - -## 1.27.1 - 2023-02-08 - -### Added - -- Nothing - -### Changed - -- Nothing - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Fix Composer --dev dependency issue with dealerdirect/phpcodesniffer-composer-installer renaming their `master` branch to `main` - - -## 1.27.0 - 2023-01-24 - -### Added - -- Option to specify a range of columns/rows for the Row/Column `isEmpty()` methods [PR #3315](https://github.com/PHPOffice/PhpSpreadsheet/pull/3315) -- Option for Cell Iterator to return a null value or create and return a new cell when accessing a cell that doesn't exist [PR #3314](https://github.com/PHPOffice/PhpSpreadsheet/pull/3314) -- Support for Structured References in the Calculation Engine [PR #3261](https://github.com/PHPOffice/PhpSpreadsheet/pull/3261) -- Limited Support for Form Controls [PR #3130](https://github.com/PHPOffice/PhpSpreadsheet/pull/3130) [Issue #2396](https://github.com/PHPOffice/PhpSpreadsheet/issues/2396) [Issue #1770](https://github.com/PHPOffice/PhpSpreadsheet/issues/1770) [Issue #2388](https://github.com/PHPOffice/PhpSpreadsheet/issues/2388) [Issue #2904](https://github.com/PHPOffice/PhpSpreadsheet/issues/2904) [Issue #2661](https://github.com/PHPOffice/PhpSpreadsheet/issues/2661) - -### Changed - -- Nothing - -### Deprecated - -- Nothing - -### Removed - -- Shared/JAMA is removed. [PR #3260](https://github.com/PHPOffice/PhpSpreadsheet/pull/3260) - -### Fixed - -- Namespace-Aware Code for SheetViewOptions, SheetProtection [PR #3230](https://github.com/PHPOffice/PhpSpreadsheet/pull/3230) -- Additional Method for XIRR if Newton-Raphson Doesn't Converge [Issue #689](https://github.com/PHPOffice/PhpSpreadsheet/issues/689) [PR #3262](https://github.com/PHPOffice/PhpSpreadsheet/pull/3262) -- Better Handling of Composite Charts [Issue #2333](https://github.com/PHPOffice/PhpSpreadsheet/issues/2333) [PR #3265](https://github.com/PHPOffice/PhpSpreadsheet/pull/3265) -- Update Column Reference for Columns Beginning with Y and Z [Issue #3263](https://github.com/PHPOffice/PhpSpreadsheet/issues/3263) [PR #3264](https://github.com/PHPOffice/PhpSpreadsheet/pull/3264) -- Honor Fit to 1-Page Height Html/Pdf [Issue #3266](https://github.com/PHPOffice/PhpSpreadsheet/issues/3266) [PR #3279](https://github.com/PHPOffice/PhpSpreadsheet/pull/3279) -- AND/OR/XOR Handling of Literal Strings [PR #3287](https://github.com/PHPOffice/PhpSpreadsheet/pull/3287) -- Xls Reader Vertical Break and Writer Page Order [Issue #3305](https://github.com/PHPOffice/PhpSpreadsheet/issues/3305) [PR #3306](https://github.com/PHPOffice/PhpSpreadsheet/pull/3306) - - -## 1.26.0 - 2022-12-21 - -### Added - -- Extended flag options for the Reader `load()` and Writer `save()` methods -- Apply Row/Column limits (1048576 and XFD) in ReferenceHelper [PR #3213](https://github.com/PHPOffice/PhpSpreadsheet/pull/3213) -- Allow the creation of In-Memory Drawings from a string of binary image data, or from a stream. [PR #3157](https://github.com/PHPOffice/PhpSpreadsheet/pull/3157) -- Xlsx Reader support for Pivot Tables [PR #2829](https://github.com/PHPOffice/PhpSpreadsheet/pull/2829) -- Permit Date/Time Entered on Spreadsheet to be calculated as Float [Issue #1416](https://github.com/PHPOffice/PhpSpreadsheet/issues/1416) [PR #3121](https://github.com/PHPOffice/PhpSpreadsheet/pull/3121) - -### Changed - -- Nothing - -### Deprecated - -- Direct update of Calculation::suppressFormulaErrors is replaced with setter. -- Font public static variable defaultColumnWidths replaced with constant DEFAULT_COLUMN_WIDTHS. -- ExcelError public static variable errorCodes replaced with constant ERROR_CODES. -- NumberFormat constant FORMAT_DATE_YYYYMMDD2 replaced with existing identical FORMAT_DATE_YYYYMMDD. - -### Removed - -- Nothing - -### Fixed - -- Fixed handling for `_xlws` prefixed functions from Office365 [Issue #3245](https://github.com/PHPOffice/PhpSpreadsheet/issues/3245) [PR #3247](https://github.com/PHPOffice/PhpSpreadsheet/pull/3247) -- Conditionals formatting rules applied to rows/columns are removed [Issue #3184](https://github.com/PHPOffice/PhpSpreadsheet/issues/3184) [PR #3213](https://github.com/PHPOffice/PhpSpreadsheet/pull/3213) -- Treat strings containing currency or accounting values as floats in Calculation Engine operations [Issue #3165](https://github.com/PHPOffice/PhpSpreadsheet/issues/3165) [PR #3189](https://github.com/PHPOffice/PhpSpreadsheet/pull/3189) -- Treat strings containing percentage values as floats in Calculation Engine operations [Issue #3155](https://github.com/PHPOffice/PhpSpreadsheet/issues/3155) [PR #3156](https://github.com/PHPOffice/PhpSpreadsheet/pull/3156) and [PR #3164](https://github.com/PHPOffice/PhpSpreadsheet/pull/3164) -- Xlsx Reader Accept Palette of Fewer than 64 Colors [Issue #3093](https://github.com/PHPOffice/PhpSpreadsheet/issues/3093) [PR #3096](https://github.com/PHPOffice/PhpSpreadsheet/pull/3096) -- Use Locale-Independent Float Conversion for Xlsx Writer Custom Property [Issue #3095](https://github.com/PHPOffice/PhpSpreadsheet/issues/3095) [PR #3099](https://github.com/PHPOffice/PhpSpreadsheet/pull/3099) -- Allow setting AutoFilter range on a single cell or row [Issue #3102](https://github.com/PHPOffice/PhpSpreadsheet/issues/3102) [PR #3111](https://github.com/PHPOffice/PhpSpreadsheet/pull/3111) -- Xlsx Reader External Data Validations Flag Missing [Issue #2677](https://github.com/PHPOffice/PhpSpreadsheet/issues/2677) [PR #3078](https://github.com/PHPOffice/PhpSpreadsheet/pull/3078) -- Reduces extra memory usage on `__destruct()` calls [PR #3092](https://github.com/PHPOffice/PhpSpreadsheet/pull/3092) -- Additional properties for Trendlines [Issue #3011](https://github.com/PHPOffice/PhpSpreadsheet/issues/3011) [PR #3028](https://github.com/PHPOffice/PhpSpreadsheet/pull/3028) -- Calculation suppressFormulaErrors fix [Issue #1531](https://github.com/PHPOffice/PhpSpreadsheet/issues/1531) [PR #3092](https://github.com/PHPOffice/PhpSpreadsheet/pull/3092) -- Permit Date/Time Entered on Spreadsheet to be Calculated as Float [Issue #1416](https://github.com/PHPOffice/PhpSpreadsheet/issues/1416) [PR #3121](https://github.com/PHPOffice/PhpSpreadsheet/pull/3121) -- Incorrect Handling of Data Validation Formula Containing Ampersand [Issue #3145](https://github.com/PHPOffice/PhpSpreadsheet/issues/3145) [PR #3146](https://github.com/PHPOffice/PhpSpreadsheet/pull/3146) -- Xlsx Namespace Handling of Drawings, RowAndColumnAttributes, MergeCells [Issue #3138](https://github.com/PHPOffice/PhpSpreadsheet/issues/3138) [PR #3136](https://github.com/PHPOffice/PhpSpreadsheet/pull/3137) -- Generation3 Copy With Image in Footer [Issue #3126](https://github.com/PHPOffice/PhpSpreadsheet/issues/3126) [PR #3140](https://github.com/PHPOffice/PhpSpreadsheet/pull/3140) -- MATCH Function Problems with Int/Float Compare and Wildcards [Issue #3141](https://github.com/PHPOffice/PhpSpreadsheet/issues/3141) [PR #3142](https://github.com/PHPOffice/PhpSpreadsheet/pull/3142) -- Fix ODS Read Filter on number-columns-repeated cell [Issue #3148](https://github.com/PHPOffice/PhpSpreadsheet/issues/3148) [PR #3149](https://github.com/PHPOffice/PhpSpreadsheet/pull/3149) -- Problems Formatting Very Small and Very Large Numbers [Issue #3128](https://github.com/PHPOffice/PhpSpreadsheet/issues/3128) [PR #3152](https://github.com/PHPOffice/PhpSpreadsheet/pull/3152) -- XlsxWrite preserve line styles for y-axis, not just x-axis [PR #3163](https://github.com/PHPOffice/PhpSpreadsheet/pull/3163) -- Xlsx Namespace Handling of Drawings, RowAndColumnAttributes, MergeCells [Issue #3138](https://github.com/PHPOffice/PhpSpreadsheet/issues/3138) [PR #3137](https://github.com/PHPOffice/PhpSpreadsheet/pull/3137) -- More Detail for Cyclic Error Messages [Issue #3169](https://github.com/PHPOffice/PhpSpreadsheet/issues/3169) [PR #3170](https://github.com/PHPOffice/PhpSpreadsheet/pull/3170) -- Improved Documentation for Deprecations - many PRs [Issue #3162](https://github.com/PHPOffice/PhpSpreadsheet/issues/3162) - - -## 1.25.2 - 2022-09-25 - -### Added - -- Nothing - -### Changed - -- Nothing - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Composer dependency clash with ezyang/htmlpurifier - - -## 1.25.0 - 2022-09-25 - -### Added - -- Implementation of the new `TEXTBEFORE()`, `TEXTAFTER()` and `TEXTSPLIT()` Excel Functions -- Implementation of the `ARRAYTOTEXT()` and `VALUETOTEXT()` Excel Functions -- Support for [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) implementation of - JpGraph library to render charts added. -- Charts: Add Gradients, Transparency, Hidden Axes, Rounded Corners, Trendlines, Date Axes. - -### Changed - -- Allow variant behaviour when merging cells [Issue #3065](https://github.com/PHPOffice/PhpSpreadsheet/issues/3065) - - Merge methods now allow an additional `$behaviour` argument. Permitted values are: - - Worksheet::MERGE_CELL_CONTENT_EMPTY - Empty the content of the hidden cells (the default behaviour) - - Worksheet::MERGE_CELL_CONTENT_HIDE - Keep the content of the hidden cells - - Worksheet::MERGE_CELL_CONTENT_MERGE - Move the content of the hidden cells into the first cell - -### Deprecated - -- Axis getLineProperty deprecated in favor of getLineColorProperty. -- Moved majorGridlines and minorGridlines from Chart to Axis. Setting either in Chart constructor or through Chart methods, or getting either using Chart methods is deprecated. -- Chart::EXCEL_COLOR_TYPE_* copied from Properties to ChartColor; use in Properties is deprecated. -- ChartColor::EXCEL_COLOR_TYPE_ARGB deprecated in favor of EXCEL_COLOR_TYPE_RGB ("A" component was never allowed). -- Misspelled Properties::LINE_STYLE_DASH_SQUERE_DOT deprecated in favor of LINE_STYLE_DASH_SQUARE_DOT. -- Clone not permitted for Spreadsheet. Spreadsheet->copy() can be used instead. - -### Removed - -- Nothing - -### Fixed - -- Fix update to defined names when inserting/deleting rows/columns [Issue #3076](https://github.com/PHPOffice/PhpSpreadsheet/issues/3076) [PR #3077](https://github.com/PHPOffice/PhpSpreadsheet/pull/3077) -- Fix DataValidation sqRef when inserting/deleting rows/columns [Issue #3056](https://github.com/PHPOffice/PhpSpreadsheet/issues/3056) [PR #3074](https://github.com/PHPOffice/PhpSpreadsheet/pull/3074) -- Named ranges not usable as anchors in OFFSET function [Issue #3013](https://github.com/PHPOffice/PhpSpreadsheet/issues/3013) -- Fully flatten an array [Issue #2955](https://github.com/PHPOffice/PhpSpreadsheet/issues/2955) [PR #2956](https://github.com/PHPOffice/PhpSpreadsheet/pull/2956) -- cellExists() and getCell() methods should support UTF-8 named cells [Issue #2987](https://github.com/PHPOffice/PhpSpreadsheet/issues/2987) [PR #2988](https://github.com/PHPOffice/PhpSpreadsheet/pull/2988) -- Spreadsheet copy fixed, clone disabled. [PR #2951](https://github.com/PHPOffice/PhpSpreadsheet/pull/2951) -- Fix PDF problems with text rotation and paper size. [Issue #1747](https://github.com/PHPOffice/PhpSpreadsheet/issues/1747) [Issue #1713](https://github.com/PHPOffice/PhpSpreadsheet/issues/1713) [PR #2960](https://github.com/PHPOffice/PhpSpreadsheet/pull/2960) -- Limited support for chart titles as formulas [Issue #2965](https://github.com/PHPOffice/PhpSpreadsheet/issues/2965) [Issue #749](https://github.com/PHPOffice/PhpSpreadsheet/issues/749) [PR #2971](https://github.com/PHPOffice/PhpSpreadsheet/pull/2971) -- Add Gradients, Transparency, and Hidden Axes to Chart [Issue #2257](https://github.com/PHPOffice/PhpSpreadsheet/issues/2257) [Issue #2229](https://github.com/PHPOffice/PhpSpreadsheet/issues/2929) [Issue #2935](https://github.com/PHPOffice/PhpSpreadsheet/issues/2935) [PR #2950](https://github.com/PHPOffice/PhpSpreadsheet/pull/2950) -- Chart Support for Rounded Corners and Trendlines [Issue #2968](https://github.com/PHPOffice/PhpSpreadsheet/issues/2968) [Issue #2815](https://github.com/PHPOffice/PhpSpreadsheet/issues/2815) [PR #2976](https://github.com/PHPOffice/PhpSpreadsheet/pull/2976) -- Add setName Method for Chart [Issue #2991](https://github.com/PHPOffice/PhpSpreadsheet/issues/2991) [PR #3001](https://github.com/PHPOffice/PhpSpreadsheet/pull/3001) -- Eliminate partial dependency on php-intl in StringHelper [Issue #2982](https://github.com/PHPOffice/PhpSpreadsheet/issues/2982) [PR #2994](https://github.com/PHPOffice/PhpSpreadsheet/pull/2994) -- Minor changes for Pdf [Issue #2999](https://github.com/PHPOffice/PhpSpreadsheet/issues/2999) [PR #3002](https://github.com/PHPOffice/PhpSpreadsheet/pull/3002) [PR #3006](https://github.com/PHPOffice/PhpSpreadsheet/pull/3006) -- Html/Pdf Do net set background color for cells using (default) nofill [PR #3016](https://github.com/PHPOffice/PhpSpreadsheet/pull/3016) -- Add support for Date Axis to Chart [Issue #2967](https://github.com/PHPOffice/PhpSpreadsheet/issues/2967) [PR #3018](https://github.com/PHPOffice/PhpSpreadsheet/pull/3018) -- Reconcile Differences Between Css and Excel for Cell Alignment [PR #3048](https://github.com/PHPOffice/PhpSpreadsheet/pull/3048) -- R1C1 Format Internationalization and Better Support for Relative Offsets [Issue #1704](https://github.com/PHPOffice/PhpSpreadsheet/issues/1704) [PR #3052](https://github.com/PHPOffice/PhpSpreadsheet/pull/3052) -- Minor Fix for Percentage Formatting [Issue #1929](https://github.com/PHPOffice/PhpSpreadsheet/issues/1929) [PR #3053](https://github.com/PHPOffice/PhpSpreadsheet/pull/3053) - -## 1.24.1 - 2022-07-18 - -### Added - -- Support for SimpleCache Interface versions 1.0, 2.0 and 3.0 -- Add Chart Axis Option textRotation [Issue #2705](https://github.com/PHPOffice/PhpSpreadsheet/issues/2705) [PR #2940](https://github.com/PHPOffice/PhpSpreadsheet/pull/2940) - -### Changed - -- Nothing - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Fix Encoding issue with Html reader (PHP 8.2 deprecation for mb_convert_encoding) [Issue #2942](https://github.com/PHPOffice/PhpSpreadsheet/issues/2942) [PR #2943](https://github.com/PHPOffice/PhpSpreadsheet/pull/2943) -- Additional Chart fixes - - Pie chart with part separated unwantedly [Issue #2506](https://github.com/PHPOffice/PhpSpreadsheet/issues/2506) [PR #2928](https://github.com/PHPOffice/PhpSpreadsheet/pull/2928) - - Chart styling is lost on simple load / save process [Issue #1797](https://github.com/PHPOffice/PhpSpreadsheet/issues/1797) [Issue #2077](https://github.com/PHPOffice/PhpSpreadsheet/issues/2077) [PR #2930](https://github.com/PHPOffice/PhpSpreadsheet/pull/2930) - - Can't create contour chart (surface 2d) [Issue #2931](https://github.com/PHPOffice/PhpSpreadsheet/issues/2931) [PR #2933](https://github.com/PHPOffice/PhpSpreadsheet/pull/2933) -- VLOOKUP Breaks When Array Contains Null Cells [Issue #2934](https://github.com/PHPOffice/PhpSpreadsheet/issues/2934) [PR #2939](https://github.com/PHPOffice/PhpSpreadsheet/pull/2939) - -## 1.24.0 - 2022-07-09 - -Note that this will be the last 1.x branch release before the 2.x release. We will maintain both branches in parallel for a time; but users are requested to update to version 2.0 once that is fully available. - -### Added - -- Added `removeComment()` method for Worksheet [PR #2875](https://github.com/PHPOffice/PhpSpreadsheet/pull/2875/files) -- Add point size option for scatter charts [Issue #2298](https://github.com/PHPOffice/PhpSpreadsheet/issues/2298) [PR #2801](https://github.com/PHPOffice/PhpSpreadsheet/pull/2801) -- Basic support for Xlsx reading/writing Chart Sheets [PR #2830](https://github.com/PHPOffice/PhpSpreadsheet/pull/2830) - - Note that a ChartSheet is still only written as a normal Worksheet containing a single chart, not as an actual ChartSheet. - -- Added Worksheet visibility in Ods Reader [PR #2851](https://github.com/PHPOffice/PhpSpreadsheet/pull/2851) and Gnumeric Reader [PR #2853](https://github.com/PHPOffice/PhpSpreadsheet/pull/2853) -- Added Worksheet visibility in Ods Writer [PR #2850](https://github.com/PHPOffice/PhpSpreadsheet/pull/2850) -- Allow Csv Reader to treat string as contents of file [Issue #1285](https://github.com/PHPOffice/PhpSpreadsheet/issues/1285) [PR #2792](https://github.com/PHPOffice/PhpSpreadsheet/pull/2792) -- Allow Csv Reader to store null string rather than leave cell empty [Issue #2840](https://github.com/PHPOffice/PhpSpreadsheet/issues/2840) [PR #2842](https://github.com/PHPOffice/PhpSpreadsheet/pull/2842) -- Provide new Worksheet methods to identify if a row or column is "empty", making allowance for different definitions of "empty": - - Treat rows/columns containing no cell records as empty (default) - - Treat cells containing a null value as empty - - Treat cells containing an empty string as empty - -### Changed - -- Modify `rangeBoundaries()`, `rangeDimension()` and `getRangeBoundaries()` Coordinate methods to work with row/column ranges as well as with cell ranges and cells [PR #2926](https://github.com/PHPOffice/PhpSpreadsheet/pull/2926) -- Better enforcement of value modification to match specified datatype when using `setValueExplicit()` -- Relax validation of merge cells to allow merge for a single cell reference [Issue #2776](https://github.com/PHPOffice/PhpSpreadsheet/issues/2776) -- Memory and speed improvements, particularly for the Cell Collection, and the Writers. - - See [the Discussion section on github](https://github.com/PHPOffice/PhpSpreadsheet/discussions/2821) for details of performance across versions -- Improved performance for removing rows/columns from a worksheet - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Xls Reader resolving absolute named ranges to relative ranges [Issue #2826](https://github.com/PHPOffice/PhpSpreadsheet/issues/2826) [PR #2827](https://github.com/PHPOffice/PhpSpreadsheet/pull/2827) -- Null value handling in the Excel Math/Trig PRODUCT() function [Issue #2833](https://github.com/PHPOffice/PhpSpreadsheet/issues/2833) [PR #2834](https://github.com/PHPOffice/PhpSpreadsheet/pull/2834) -- Invalid Print Area defined in Xlsx corrupts internal storage of print area [Issue #2848](https://github.com/PHPOffice/PhpSpreadsheet/issues/2848) [PR #2849](https://github.com/PHPOffice/PhpSpreadsheet/pull/2849) -- Time interval formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772) -- Copy from Xls(x) to Html/Pdf loses drawings [PR #2788](https://github.com/PHPOffice/PhpSpreadsheet/pull/2788) -- Html Reader converting cell containing 0 to null string [Issue #2810](https://github.com/PHPOffice/PhpSpreadsheet/issues/2810) [PR #2813](https://github.com/PHPOffice/PhpSpreadsheet/pull/2813) -- Many fixes for Charts, especially, but not limited to, Scatter, Bubble, and Surface charts. [Issue #2762](https://github.com/PHPOffice/PhpSpreadsheet/issues/2762) [Issue #2299](https://github.com/PHPOffice/PhpSpreadsheet/issues/2299) [Issue #2700](https://github.com/PHPOffice/PhpSpreadsheet/issues/2700) [Issue #2817](https://github.com/PHPOffice/PhpSpreadsheet/issues/2817) [Issue #2763](https://github.com/PHPOffice/PhpSpreadsheet/issues/2763) [Issue #2219](https://github.com/PHPOffice/PhpSpreadsheet/issues/2219) [Issue #2863](https://github.com/PHPOffice/PhpSpreadsheet/issues/2863) [PR #2828](https://github.com/PHPOffice/PhpSpreadsheet/pull/2828) [PR #2841](https://github.com/PHPOffice/PhpSpreadsheet/pull/2841) [PR #2846](https://github.com/PHPOffice/PhpSpreadsheet/pull/2846) [PR #2852](https://github.com/PHPOffice/PhpSpreadsheet/pull/2852) [PR #2856](https://github.com/PHPOffice/PhpSpreadsheet/pull/2856) [PR #2865](https://github.com/PHPOffice/PhpSpreadsheet/pull/2865) [PR #2872](https://github.com/PHPOffice/PhpSpreadsheet/pull/2872) [PR #2879](https://github.com/PHPOffice/PhpSpreadsheet/pull/2879) [PR #2898](https://github.com/PHPOffice/PhpSpreadsheet/pull/2898) [PR #2906](https://github.com/PHPOffice/PhpSpreadsheet/pull/2906) [PR #2922](https://github.com/PHPOffice/PhpSpreadsheet/pull/2922) [PR #2923](https://github.com/PHPOffice/PhpSpreadsheet/pull/2923) -- Adjust both coordinates for two-cell anchors when rows/columns are added/deleted. [Issue #2908](https://github.com/PHPOffice/PhpSpreadsheet/issues/2908) [PR #2909](https://github.com/PHPOffice/PhpSpreadsheet/pull/2909) -- Keep calculated string results below 32K. [PR #2921](https://github.com/PHPOffice/PhpSpreadsheet/pull/2921) -- Filter out illegal Unicode char values FFFE/FFFF. [Issue #2897](https://github.com/PHPOffice/PhpSpreadsheet/issues/2897) [PR #2910](https://github.com/PHPOffice/PhpSpreadsheet/pull/2910) -- Better handling of REF errors and propagation of all errors in Calculation engine. [PR #2902](https://github.com/PHPOffice/PhpSpreadsheet/pull/2902) -- Calculating Engine regexp for Column/Row references when there are multiple quoted worksheet references in the formula [Issue #2874](https://github.com/PHPOffice/PhpSpreadsheet/issues/2874) [PR #2899](https://github.com/PHPOffice/PhpSpreadsheet/pull/2899) - -## 1.23.0 - 2022-04-24 - -### Added - -- Ods Writer support for Freeze Pane [Issue #2013](https://github.com/PHPOffice/PhpSpreadsheet/issues/2013) [PR #2755](https://github.com/PHPOffice/PhpSpreadsheet/pull/2755) -- Ods Writer support for setting column width/row height (including the use of AutoSize) [Issue #2346](https://github.com/PHPOffice/PhpSpreadsheet/issues/2346) [PR #2753](https://github.com/PHPOffice/PhpSpreadsheet/pull/2753) -- Introduced CellAddress, CellRange, RowRange and ColumnRange value objects that can be used as an alternative to a string value (e.g. `'C5'`, `'B2:D4'`, `'2:2'` or `'B:C'`) in appropriate contexts. -- Implementation of the FILTER(), SORT(), SORTBY() and UNIQUE() Lookup/Reference (array) functions. -- Implementation of the ISREF() Information function. -- Added support for reading "formatted" numeric values from Csv files; although default behaviour of reading these values as strings is preserved. - - (i.e a value of "12,345.67" can be read as numeric `12345.67`, not simply as a string `"12,345.67"`, if the `castFormattedNumberToNumeric()` setting is enabled. - - This functionality is locale-aware, using the server's locale settings to identify the thousands and decimal separators. - -- Support for two cell anchor drawing of images. [#2532](https://github.com/PHPOffice/PhpSpreadsheet/pull/2532) [#2674](https://github.com/PHPOffice/PhpSpreadsheet/pull/2674) -- Limited support for Xls Reader to handle Conditional Formatting: - - Ranges and Rules are read, but style is currently limited to font size, weight and color; and to fill style and color. - -- Add ability to suppress Mac line ending check for CSV [#2623](https://github.com/PHPOffice/PhpSpreadsheet/pull/2623) -- Initial support for creating and writing Tables (Xlsx Writer only) [PR #2671](https://github.com/PHPOffice/PhpSpreadsheet/pull/2671) - - See `/samples/Table` for examples of use. - - Note that PreCalculateFormulas needs to be disabled when saving spreadsheets containing tables with formulae (totals or column formulae). - -### Changed - -- Gnumeric Reader now loads number formatting for cells. -- Gnumeric Reader now correctly identifies selected worksheet and selected cells in a worksheet. -- Some Refactoring of the Ods Reader, moving all formula and address translation from Ods to Excel into a separate class to eliminate code duplication and ensure consistency. -- Make Boolean Conversion in Csv Reader locale-aware when using the String Value Binder. - - This is determined by the Calculation Engine locale setting. - - (i.e. `"Vrai"` wil be converted to a boolean `true` if the Locale is set to `fr`.) -- Allow `psr/simple-cache` 2.x - -### Deprecated - -- All Excel Function implementations in `Calculation\Functions` (including the Error functions) have been moved to dedicated classes for groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted. -- Worksheet methods that reference cells "byColumnandRow". All such methods have an equivalent that references the cell by its address (e.g. '`E3'` rather than `5, 3`). - - These functions now accept either a cell address string (`'E3')` or an array with columnId and rowId (`[5, 3]`) or a new `CellAddress` object as their `cellAddress`/`coordinate` argument. - This includes the methods: - - `setCellValueByColumnAndRow()` use the equivalent `setCellValue()` - - `setCellValueExplicitByColumnAndRow()` use the equivalent `setCellValueExplicit()` - - `getCellByColumnAndRow()` use the equivalent `getCell()` - - `cellExistsByColumnAndRow()` use the equivalent `cellExists()` - - `getStyleByColumnAndRow()` use the equivalent `getStyle()` - - `setBreakByColumnAndRow()` use the equivalent `setBreak()` - - `mergeCellsByColumnAndRow()` use the equivalent `mergeCells()` - - `unmergeCellsByColumnAndRow()` use the equivalent `unmergeCells()` - - `protectCellsByColumnAndRow()` use the equivalent `protectCells()` - - `unprotectCellsByColumnAndRow()` use the equivalent `unprotectCells()` - - `setAutoFilterByColumnAndRow()` use the equivalent `setAutoFilter()` - - `freezePaneByColumnAndRow()` use the equivalent `freezePane()` - - `getCommentByColumnAndRow()` use the equivalent `getComment()` - - `setSelectedCellByColumnAndRow()` use the equivalent `setSelectedCells()` - - This change provides more consistency in the methods (not every "by cell address" method has an equivalent "byColumnAndRow" method); - and the "by cell address" methods often provide more flexibility, such as allowing a range of cells, or referencing them by passing the defined name of a named range as the argument. - -### Removed - -- Nothing - -### Fixed - -- Make allowance for the AutoFilter dropdown icon in the first row of an Autofilter range when using Autosize columns. [Issue #2413](https://github.com/PHPOffice/PhpSpreadsheet/issues/2413) [PR #2754](https://github.com/PHPOffice/PhpSpreadsheet/pull/2754) -- Support for "chained" ranges (e.g. `A5:C10:C20:F1`) in the Calculation Engine; and also support for using named ranges with the Range operator (e.g. `NamedRange1:NamedRange2`) [Issue #2730](https://github.com/PHPOffice/PhpSpreadsheet/issues/2730) [PR #2746](https://github.com/PHPOffice/PhpSpreadsheet/pull/2746) -- Update Conditional Formatting ranges and rule conditions when inserting/deleting rows/columns [Issue #2678](https://github.com/PHPOffice/PhpSpreadsheet/issues/2678) [PR #2689](https://github.com/PHPOffice/PhpSpreadsheet/pull/2689) -- Allow `INDIRECT()` to accept row/column ranges as well as cell ranges [PR #2687](https://github.com/PHPOffice/PhpSpreadsheet/pull/2687) -- Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address. -- Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet. -- Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae. -- Fix for setting Active Sheet to the first loaded worksheet when bookViews element isn't defined [Issue #2666](https://github.com/PHPOffice/PhpSpreadsheet/issues/2666) [PR #2669](https://github.com/PHPOffice/PhpSpreadsheet/pull/2669) -- Fixed behaviour of XLSX font style vertical align settings [PR #2619](https://github.com/PHPOffice/PhpSpreadsheet/pull/2619) -- Resolved formula translations to handle separators (row and column) for array functions as well as for function argument separators; and cleanly handle nesting levels. - - Note that this method is used when translating Excel functions between `en_us` and other locale languages, as well as when converting formulae between different spreadsheet formats (e.g. Ods to Excel). - - Nor is this a perfect solution, as there may still be issues when function calls have array arguments that themselves contain function calls; but it's still better than the current logic. -- Fix for escaping double quotes within a formula [Issue #1971](https://github.com/PHPOffice/PhpSpreadsheet/issues/1971) [PR #2651](https://github.com/PHPOffice/PhpSpreadsheet/pull/2651) -- Change open mode for output from `wb+` to `wb` [Issue #2372](https://github.com/PHPOffice/PhpSpreadsheet/issues/2372) [PR #2657](https://github.com/PHPOffice/PhpSpreadsheet/pull/2657) -- Use color palette if supplied [Issue #2499](https://github.com/PHPOffice/PhpSpreadsheet/issues/2499) [PR #2595](https://github.com/PHPOffice/PhpSpreadsheet/pull/2595) -- Xls reader treat drawing offsets as int rather than float [PR #2648](https://github.com/PHPOffice/PhpSpreadsheet/pull/2648) -- Handle booleans in conditional styles properly [PR #2654](https://github.com/PHPOffice/PhpSpreadsheet/pull/2654) -- Fix for reading files in the root directory of a ZipFile, which should not be prefixed by relative paths ("./") as dirname($filename) does by default. -- Fix invalid style of cells in empty columns with columnDimensions and rows with rowDimensions in added external sheet. [PR #2739](https://github.com/PHPOffice/PhpSpreadsheet/pull/2739) -- Time Interval Formatting [Issue #2768](https://github.com/PHPOffice/PhpSpreadsheet/issues/2768) [PR #2772](https://github.com/PHPOffice/PhpSpreadsheet/pull/2772) - -## 1.22.0 - 2022-02-18 - -### Added - -- Namespacing phase 2 - styles. -[PR #2471](https://github.com/PHPOffice/PhpSpreadsheet/pull/2471) - -- Improved support for passing of array arguments to Excel function implementations to return array results (where appropriate). [Issue #2551](https://github.com/PHPOffice/PhpSpreadsheet/issues/2551) - - This is the first stage in an ongoing process of adding array support to all appropriate function implementations, -- Support for the Excel365 Math/Trig SEQUENCE() function [PR #2536](https://github.com/PHPOffice/PhpSpreadsheet/pull/2536) -- Support for the Excel365 Math/Trig RANDARRAY() function [PR #2540](https://github.com/PHPOffice/PhpSpreadsheet/pull/2540) - - Note that the Spill Operator is not yet supported in the Calculation Engine; but this can still be useful for defining array constants. -- Improved support for Conditional Formatting Rules [PR #2491](https://github.com/PHPOffice/PhpSpreadsheet/pull/2491) - - Provide support for a wider range of Conditional Formatting Rules for Xlsx Reader/Writer: - - Cells Containing (cellIs) - - Specific Text (containing, notContaining, beginsWith, endsWith) - - Dates Occurring (all supported timePeriods) - - Blanks/NoBlanks - - Errors/NoErrors - - Duplicates/Unique - - Expression - - Provision of CF Wizards (for all the above listed rule types) to help create/modify CF Rules without having to manage all the combinations of types/operators, and the complexities of formula expressions, or the text/timePeriod attributes. - - See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/conditional-formatting/) for details - - - Full support of the above CF Rules for the Xlsx Reader and Writer; even when the file being loaded has CF rules listed in the `` element for the worksheet rather than the `` element. - - Provision of a CellMatcher to identify if rules are matched for a cell, and which matching style will be applied. - - Improved documentation and examples, covering all supported CF rule types. - - Add support for one digit decimals (FORMAT_NUMBER_0, FORMAT_PERCENTAGE_0). [PR #2525](https://github.com/PHPOffice/PhpSpreadsheet/pull/2525) - - Initial work enabling Excel function implementations for handling arrays as arguments when used in "array formulae" [#2562](https://github.com/PHPOffice/PhpSpreadsheet/issues/2562) - - Enable most of the Date/Time functions to accept array arguments [#2573](https://github.com/PHPOffice/PhpSpreadsheet/issues/2573) - - Array ready functions - Text, Math/Trig, Statistical, Engineering and Logical [#2580](https://github.com/PHPOffice/PhpSpreadsheet/issues/2580) - -### Changed - -- Additional Russian translations for Excel Functions (courtesy of aleks-samurai). -- Improved code coverage for NumberFormat. [PR #2556](https://github.com/PHPOffice/PhpSpreadsheet/pull/2556) -- Extract some methods from the Calculation Engine into dedicated classes [#2537](https://github.com/PHPOffice/PhpSpreadsheet/issues/2537) -- Eliminate calls to `flattenSingleValue()` that are no longer required when we're checking for array values as arguments [#2590](https://github.com/PHPOffice/PhpSpreadsheet/issues/2590) - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Fixed `ReferenceHelper@insertNewBefore` behavior when removing column before last column with null value [PR #2541](https://github.com/PHPOffice/PhpSpreadsheet/pull/2541) -- Fix bug with `DOLLARDE()` and `DOLLARFR()` functions when the dollar value is negative [Issue #2578](https://github.com/PHPOffice/PhpSpreadsheet/issues/2578) [PR #2579](https://github.com/PHPOffice/PhpSpreadsheet/pull/2579) -- Fix partial function name matching when translating formulae from Russian to English [Issue #2533](https://github.com/PHPOffice/PhpSpreadsheet/issues/2533) [PR #2534](https://github.com/PHPOffice/PhpSpreadsheet/pull/2534) -- Various bugs related to Conditional Formatting Rules, and errors in the Xlsx Writer for Conditional Formatting [PR #2491](https://github.com/PHPOffice/PhpSpreadsheet/pull/2491) -- Xlsx Reader merge range fixes. [Issue #2501](https://github.com/PHPOffice/PhpSpreadsheet/issues/2501) [PR #2504](https://github.com/PHPOffice/PhpSpreadsheet/pull/2504) -- Handle explicit "date" type for Cell in Xlsx Reader. [Issue #2373](https://github.com/PHPOffice/PhpSpreadsheet/issues/2373) [PR #2485](https://github.com/PHPOffice/PhpSpreadsheet/pull/2485) -- Recalibrate Row/Column Dimensions after removeRow/Column. [Issue #2442](https://github.com/PHPOffice/PhpSpreadsheet/issues/2442) [PR #2486](https://github.com/PHPOffice/PhpSpreadsheet/pull/2486) -- Refinement for XIRR. [Issue #2469](https://github.com/PHPOffice/PhpSpreadsheet/issues/2469) [PR #2487](https://github.com/PHPOffice/PhpSpreadsheet/pull/2487) -- Xlsx Reader handle cell with non-null explicit type but null value. [Issue #2488](https://github.com/PHPOffice/PhpSpreadsheet/issues/2488) [PR #2489](https://github.com/PHPOffice/PhpSpreadsheet/pull/2489) -- Xlsx Reader fix height and width for oneCellAnchorDrawings. [PR #2492](https://github.com/PHPOffice/PhpSpreadsheet/pull/2492) -- Fix rounding error in NumberFormat::NUMBER_PERCENTAGE, NumberFormat::NUMBER_PERCENTAGE_00. [PR #2555](https://github.com/PHPOffice/PhpSpreadsheet/pull/2555) -- Don't treat thumbnail file as xml. [Issue #2516](https://github.com/PHPOffice/PhpSpreadsheet/issues/2516) [PR #2517](https://github.com/PHPOffice/PhpSpreadsheet/pull/2517) -- Eliminating Xlsx Reader warning when no sz tag for RichText. [Issue #2542](https://github.com/PHPOffice/PhpSpreadsheet/issues/2542) [PR #2550](https://github.com/PHPOffice/PhpSpreadsheet/pull/2550) -- Fix Xlsx/Xls Writer handling of inline strings. [Issue #353](https://github.com/PHPOffice/PhpSpreadsheet/issues/353) [PR #2569](https://github.com/PHPOffice/PhpSpreadsheet/pull/2569) -- Richtext colors were not being read correctly after namespace change [#2458](https://github.com/PHPOffice/PhpSpreadsheet/issues/2458) -- Fix discrepancy between the way markdown tables are rendered in ReadTheDocs and in PHPStorm [#2520](https://github.com/PHPOffice/PhpSpreadsheet/issues/2520) -- Update Russian Functions Text File [#2557](https://github.com/PHPOffice/PhpSpreadsheet/issues/2557) -- Fix documentation, instantiation example [#2564](https://github.com/PHPOffice/PhpSpreadsheet/issues/2564) - - -## 1.21.0 - 2022-01-06 - -### Added - -- Ability to add a picture to the background of the comment. Supports four image formats: png, jpeg, gif, bmp. New `Comment::setSizeAsBackgroundImage()` to change the size of a comment to the size of a background image. [Issue #1547](https://github.com/PHPOffice/PhpSpreadsheet/issues/1547) [PR #2422](https://github.com/PHPOffice/PhpSpreadsheet/pull/2422) -- Ability to set default paper size and orientation [PR #2410](https://github.com/PHPOffice/PhpSpreadsheet/pull/2410) -- Ability to extend AutoFilter to Maximum Row [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414) - -### Changed - -- Xlsx Writer will evaluate AutoFilter only if it is as yet unevaluated, or has changed since it was last evaluated [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414) - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Rounding in `NumberFormatter` [Issue #2385](https://github.com/PHPOffice/PhpSpreadsheet/issues/2385) [PR #2399](https://github.com/PHPOffice/PhpSpreadsheet/pull/2399) -- Support for themes [Issue #2075](https://github.com/PHPOffice/PhpSpreadsheet/issues/2075) [Issue #2387](https://github.com/PHPOffice/PhpSpreadsheet/issues/2387) [PR #2403](https://github.com/PHPOffice/PhpSpreadsheet/pull/2403) -- Read spreadsheet with `#` in name [Issue #2405](https://github.com/PHPOffice/PhpSpreadsheet/issues/2405) [PR #2409](https://github.com/PHPOffice/PhpSpreadsheet/pull/2409) -- Improve PDF support for page size and orientation [Issue #1691](https://github.com/PHPOffice/PhpSpreadsheet/issues/1691) [PR #2410](https://github.com/PHPOffice/PhpSpreadsheet/pull/2410) -- Wildcard handling issues in text match [Issue #2430](https://github.com/PHPOffice/PhpSpreadsheet/issues/2430) [PR #2431](https://github.com/PHPOffice/PhpSpreadsheet/pull/2431) -- Respect DataType in `insertNewBefore` [PR #2433](https://github.com/PHPOffice/PhpSpreadsheet/pull/2433) -- Handle rows explicitly hidden after AutoFilter [Issue #1641](https://github.com/PHPOffice/PhpSpreadsheet/issues/1641) [PR #2414](https://github.com/PHPOffice/PhpSpreadsheet/pull/2414) -- Special characters in image file name [Issue #1470](https://github.com/PHPOffice/PhpSpreadsheet/issues/1470) [Issue #2415](https://github.com/PHPOffice/PhpSpreadsheet/issues/2415) [PR #2416](https://github.com/PHPOffice/PhpSpreadsheet/pull/2416) -- Mpdf with very many styles [Issue #2432](https://github.com/PHPOffice/PhpSpreadsheet/issues/2432) [PR #2434](https://github.com/PHPOffice/PhpSpreadsheet/pull/2434) -- Name clashes between parsed and unparsed drawings [Issue #1767](https://github.com/PHPOffice/PhpSpreadsheet/issues/1767) [Issue #2396](https://github.com/PHPOffice/PhpSpreadsheet/issues/2396) [PR #2423](https://github.com/PHPOffice/PhpSpreadsheet/pull/2423) -- Fill pattern start and end colors [Issue #2441](https://github.com/PHPOffice/PhpSpreadsheet/issues/2441) [PR #2444](https://github.com/PHPOffice/PhpSpreadsheet/pull/2444) -- General style specified in wrong case [Issue #2450](https://github.com/PHPOffice/PhpSpreadsheet/issues/2450) [PR #2451](https://github.com/PHPOffice/PhpSpreadsheet/pull/2451) -- Null passed to `AutoFilter::setRange()` [Issue #2281](https://github.com/PHPOffice/PhpSpreadsheet/issues/2281) [PR #2454](https://github.com/PHPOffice/PhpSpreadsheet/pull/2454) -- Another undefined index in Xls reader (#2470) [Issue #2463](https://github.com/PHPOffice/PhpSpreadsheet/issues/2463) [PR #2470](https://github.com/PHPOffice/PhpSpreadsheet/pull/2470) -- Allow single-cell checks on conditional styles, even when the style is configured for a range of cells (#) [PR #2483](https://github.com/PHPOffice/PhpSpreadsheet/pull/2483) - -## 1.20.0 - 2021-11-23 - -### Added - -- Xlsx Writer Support for WMF Files [#2339](https://github.com/PHPOffice/PhpSpreadsheet/issues/2339) -- Use standard temporary file for internal use of HTMLPurifier [#2383](https://github.com/PHPOffice/PhpSpreadsheet/issues/2383) - -### Changed - -- Drop support for PHP 7.2, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support -- Use native typing for objects that were already documented as such - -### Deprecated - -- Nothing - -### Removed - -- Nothing - -### Fixed - -- Fixed null conversation for strToUpper [#2292](https://github.com/PHPOffice/PhpSpreadsheet/issues/2292) -- Fixed Trying to access array offset on value of type null (Xls Reader) [#2315](https://github.com/PHPOffice/PhpSpreadsheet/issues/2315) -- Don't corrupt XLSX files containing data validation [#2377](https://github.com/PHPOffice/PhpSpreadsheet/issues/2377) -- Non-fixed cells were not updated if shared formula has a fixed cell [#2354](https://github.com/PHPOffice/PhpSpreadsheet/issues/2354) -- Declare key of generic ArrayObject -- CSV reader better support for boolean values [#2374](https://github.com/PHPOffice/PhpSpreadsheet/pull/2374) -- Some ZIP file could not be read [#2376](https://github.com/PHPOffice/PhpSpreadsheet/pull/2376) -- Fix regression were hyperlinks could not be read [#2391](https://github.com/PHPOffice/PhpSpreadsheet/pull/2391) -- AutoFilter Improvements [#2393](https://github.com/PHPOffice/PhpSpreadsheet/pull/2393) -- Don't corrupt file when using chart with fill color [#589](https://github.com/PHPOffice/PhpSpreadsheet/pull/589) -- Restore imperfect array formula values in xlsx writer [#2343](https://github.com/PHPOffice/PhpSpreadsheet/pull/2343) -- Restore explicit list of changes to PHPExcel migration document [#1546](https://github.com/PHPOffice/PhpSpreadsheet/issues/1546) - -## 1.19.0 - 2021-10-31 - -### Added - -- Ability to set style on named range, and validate input to setSelectedCells [Issue #2279](https://github.com/PHPOffice/PhpSpreadsheet/issues/2279) [PR #2280](https://github.com/PHPOffice/PhpSpreadsheet/pull/2280) -- Process comments in Sylk file [Issue #2276](https://github.com/PHPOffice/PhpSpreadsheet/issues/2276) [PR #2277](https://github.com/PHPOffice/PhpSpreadsheet/pull/2277) -- Addition of Custom Properties to Ods Writer, and 32-bit-safe timestamps for Document Properties [PR #2113](https://github.com/PHPOffice/PhpSpreadsheet/pull/2113) -- Added callback to CSV reader to set user-specified defaults for various properties (especially for escape which has a poor PHP-inherited default of backslash which does not correspond with Excel) [PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103) -- Phase 1 of better namespace handling for Xlsx, resolving many open issues [PR #2173](https://github.com/PHPOffice/PhpSpreadsheet/pull/2173) [PR #2204](https://github.com/PHPOffice/PhpSpreadsheet/pull/2204) [PR #2303](https://github.com/PHPOffice/PhpSpreadsheet/pull/2303) -- Add ability to extract images if source is a URL [Issue #1997](https://github.com/PHPOffice/PhpSpreadsheet/issues/1997) [PR #2072](https://github.com/PHPOffice/PhpSpreadsheet/pull/2072) -- Support for passing flags in the Reader `load()` and Writer `save()`methods, and through the IOFactory, to set behaviours [PR #2136](https://github.com/PHPOffice/PhpSpreadsheet/pull/2136) - - See [documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/reading-and-writing-to-file/#readerwriter-flags) for details -- More flexibility in the StringValueBinder to determine what datatypes should be treated as strings [PR #2138](https://github.com/PHPOffice/PhpSpreadsheet/pull/2138) -- Helper class for conversion between css size Units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`) [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145) -- Allow Row height and Column Width to be set using different units of measure (`px`, `pt`, `pc`, `in`, `cm`, `mm`), rather than only in points or MS Excel column width units [PR #2152](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145) -- Ability to stream to an Amazon S3 bucket [Issue #2249](https://github.com/PHPOffice/PhpSpreadsheet/issues/2249) -- Provided a Size Helper class to validate size values (pt, px, em) [PR #1694](https://github.com/PHPOffice/PhpSpreadsheet/pull/1694) - -### Changed - -- Nothing. - -### Deprecated - -- PHP 8.1 will deprecate auto_detect_line_endings. As a result of this change, Csv Reader using some release after PHP8.1 will no longer be able to handle a Csv with Mac line endings. - -### Removed - -- Nothing. - -### Fixed - -- Unexpected format in Xlsx Timestamp [Issue #2331](https://github.com/PHPOffice/PhpSpreadsheet/issues/2331) [PR #2332](https://github.com/PHPOffice/PhpSpreadsheet/pull/2332) -- Corrections for HLOOKUP [Issue #2123](https://github.com/PHPOffice/PhpSpreadsheet/issues/2123) [PR #2330](https://github.com/PHPOffice/PhpSpreadsheet/pull/2330) -- Corrections for Xlsx Read Comments [Issue #2316](https://github.com/PHPOffice/PhpSpreadsheet/issues/2316) [PR #2329](https://github.com/PHPOffice/PhpSpreadsheet/pull/2329) -- Lowercase Calibri font names [Issue #2273](https://github.com/PHPOffice/PhpSpreadsheet/issues/2273) [PR #2325](https://github.com/PHPOffice/PhpSpreadsheet/pull/2325) -- isFormula Referencing Sheet with Space in Title [Issue #2304](https://github.com/PHPOffice/PhpSpreadsheet/issues/2304) [PR #2306](https://github.com/PHPOffice/PhpSpreadsheet/pull/2306) -- Xls Reader Fatal Error due to Undefined Offset [Issue #1114](https://github.com/PHPOffice/PhpSpreadsheet/issues/1114) [PR #2308](https://github.com/PHPOffice/PhpSpreadsheet/pull/2308) -- Permit Csv Reader delimiter to be set to null [Issue #2287](https://github.com/PHPOffice/PhpSpreadsheet/issues/2287) [PR #2288](https://github.com/PHPOffice/PhpSpreadsheet/pull/2288) -- Csv Reader did not handle booleans correctly [PR #2232](https://github.com/PHPOffice/PhpSpreadsheet/pull/2232) -- Problems when deleting sheet with local defined name [Issue #2266](https://github.com/PHPOffice/PhpSpreadsheet/issues/2266) [PR #2284](https://github.com/PHPOffice/PhpSpreadsheet/pull/2284) -- Worksheet passwords were not always handled correctly [Issue #1897](https://github.com/PHPOffice/PhpSpreadsheet/issues/1897) [PR #2197](https://github.com/PHPOffice/PhpSpreadsheet/pull/2197) -- Gnumeric Reader will now distinguish between Created and Modified timestamp [PR #2133](https://github.com/PHPOffice/PhpSpreadsheet/pull/2133) -- Xls Reader will now handle MACCENTRALEUROPE with or without hyphen [Issue #549](https://github.com/PHPOffice/PhpSpreadsheet/issues/549) [PR #2213](https://github.com/PHPOffice/PhpSpreadsheet/pull/2213) -- Tweaks to input file validation [Issue #1718](https://github.com/PHPOffice/PhpSpreadsheet/issues/1718) [PR #2217](https://github.com/PHPOffice/PhpSpreadsheet/pull/2217) -- Html Reader did not handle comments correctly [Issue #2234](https://github.com/PHPOffice/PhpSpreadsheet/issues/2234) [PR #2235](https://github.com/PHPOffice/PhpSpreadsheet/pull/2235) -- Apache OpenOffice Uses Unexpected Case for General format [Issue #2239](https://github.com/PHPOffice/PhpSpreadsheet/issues/2239) [PR #2242](https://github.com/PHPOffice/PhpSpreadsheet/pull/2242) -- Problems with fraction formatting [Issue #2253](https://github.com/PHPOffice/PhpSpreadsheet/issues/2253) [PR #2254](https://github.com/PHPOffice/PhpSpreadsheet/pull/2254) -- Xlsx Reader had problems reading file with no styles.xml or empty styles.xml [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246) [PR #2247](https://github.com/PHPOffice/PhpSpreadsheet/pull/2247) -- Xlsx Reader did not read Data Validation flags correctly [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225) -- Better handling of empty arguments in Calculation engine [PR #2143](https://github.com/PHPOffice/PhpSpreadsheet/pull/2143) -- Many fixes for Autofilter [Issue #2216](https://github.com/PHPOffice/PhpSpreadsheet/issues/2216) [PR #2141](https://github.com/PHPOffice/PhpSpreadsheet/pull/2141) [PR #2162](https://github.com/PHPOffice/PhpSpreadsheet/pull/2162) [PR #2218](https://github.com/PHPOffice/PhpSpreadsheet/pull/2218) -- Locale generator will now use Unix line endings even on Windows [Issue #2172](https://github.com/PHPOffice/PhpSpreadsheet/issues/2172) [PR #2174](https://github.com/PHPOffice/PhpSpreadsheet/pull/2174) -- Support differences in implementation of Text functions between Excel/Ods/Gnumeric [PR #2151](https://github.com/PHPOffice/PhpSpreadsheet/pull/2151) -- Fixes to places where PHP8.1 enforces new or previously unenforced restrictions [PR #2137](https://github.com/PHPOffice/PhpSpreadsheet/pull/2137) [PR #2191](https://github.com/PHPOffice/PhpSpreadsheet/pull/2191) [PR #2231](https://github.com/PHPOffice/PhpSpreadsheet/pull/2231) -- Clone for HashTable was incorrect [PR #2130](https://github.com/PHPOffice/PhpSpreadsheet/pull/2130) -- Xlsx Reader was not evaluating Document Security Lock correctly [PR #2128](https://github.com/PHPOffice/PhpSpreadsheet/pull/2128) -- Error in COUPNCD handling end of month [Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116) [PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119) -- Xls Writer Parser did not handle concatenation operator correctly [PR #2080](https://github.com/PHPOffice/PhpSpreadsheet/pull/2080) -- Xlsx Writer did not handle boolean false correctly [Issue #2082](https://github.com/PHPOffice/PhpSpreadsheet/issues/2082) [PR #2087](https://github.com/PHPOffice/PhpSpreadsheet/pull/2087) -- SUM needs to treat invalid strings differently depending on whether they come from a cell or are used as literals [Issue #2042](https://github.com/PHPOffice/PhpSpreadsheet/issues/2042) [PR #2045](https://github.com/PHPOffice/PhpSpreadsheet/pull/2045) -- Html reader could have set illegal coordinates when dealing with embedded tables [Issue #2029](https://github.com/PHPOffice/PhpSpreadsheet/issues/2029) [PR #2032](https://github.com/PHPOffice/PhpSpreadsheet/pull/2032) -- Documentation for printing gridlines was wrong [PR #2188](https://github.com/PHPOffice/PhpSpreadsheet/pull/2188) -- Return Value Error - DatabaseAbstruct::buildQuery() return null but must be string [Issue #2158](https://github.com/PHPOffice/PhpSpreadsheet/issues/2158) [PR #2160](https://github.com/PHPOffice/PhpSpreadsheet/pull/2160) -- Xlsx reader not recognize data validations that references another sheet [Issue #1432](https://github.com/PHPOffice/PhpSpreadsheet/issues/1432) [Issue #2149](https://github.com/PHPOffice/PhpSpreadsheet/issues/2149) [PR #2150](https://github.com/PHPOffice/PhpSpreadsheet/pull/2150) [PR #2265](https://github.com/PHPOffice/PhpSpreadsheet/pull/2265) -- Don't calculate cell width for autosize columns if a cell contains a null or empty string value [Issue #2165](https://github.com/PHPOffice/PhpSpreadsheet/issues/2165) [PR #2167](https://github.com/PHPOffice/PhpSpreadsheet/pull/2167) -- Allow negative interest rate values in a number of the Financial functions (`PPMT()`, `PMT()`, `FV()`, `PV()`, `NPER()`, etc) [Issue #2163](https://github.com/PHPOffice/PhpSpreadsheet/issues/2163) [PR #2164](https://github.com/PHPOffice/PhpSpreadsheet/pull/2164) -- Xls Reader changing grey background to black in Excel template [Issue #2147](https://github.com/PHPOffice/PhpSpreadsheet/issues/2147) [PR #2156](https://github.com/PHPOffice/PhpSpreadsheet/pull/2156) -- Column width and Row height styles in the Html Reader when the value includes a unit of measure [Issue #2145](https://github.com/PHPOffice/PhpSpreadsheet/issues/2145). -- Data Validation flags not set correctly when reading XLSX files [Issue #2224](https://github.com/PHPOffice/PhpSpreadsheet/issues/2224) [PR #2225](https://github.com/PHPOffice/PhpSpreadsheet/pull/2225) -- Reading XLSX files without styles.xml throws an exception [Issue #2246](https://github.com/PHPOffice/PhpSpreadsheet/issues/2246) -- Improved performance of `Style::applyFromArray()` when applied to several cells [PR #1785](https://github.com/PHPOffice/PhpSpreadsheet/issues/1785). -- Improve XLSX parsing speed if no readFilter is applied (again) - [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772) - -## 1.18.0 - 2021-05-31 - -### Added - -- Enhancements to CSV Reader, allowing options to be set when using `IOFactory::load()` with a callback to set delimiter, enclosure, charset etc [PR #2103](https://github.com/PHPOffice/PhpSpreadsheet/pull/2103) - See [documentation](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/docs/topics/reading-and-writing-to-file.md#csv-comma-separated-values) for details. -- Implemented basic AutoFiltering for Ods Reader and Writer [PR #2053](https://github.com/PHPOffice/PhpSpreadsheet/pull/2053) -- Implemented basic AutoFiltering for Gnumeric Reader [PR #2055](https://github.com/PHPOffice/PhpSpreadsheet/pull/2055) -- Improved support for Row and Column ranges in formulae [Issue #1755](https://github.com/PHPOffice/PhpSpreadsheet/issues/1755) [PR #2028](https://github.com/PHPOffice/PhpSpreadsheet/pull/2028) -- Implemented URLENCODE() Web Function -- Implemented the CHITEST(), CHISQ.DIST() and CHISQ.INV() and equivalent Statistical functions, for both left- and right-tailed distributions. -- Support for ActiveSheet and SelectedCells in the ODS Reader and Writer [PR #1908](https://github.com/PHPOffice/PhpSpreadsheet/pull/1908) -- Support for notContainsText Conditional Style in xlsx [Issue #984](https://github.com/PHPOffice/PhpSpreadsheet/issues/984) - -### Changed - -- Use of `nb` rather than `no` as the locale code for Norsk Bokmål. - -### Deprecated - -- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted. - -### Removed - -- Use of `nb` rather than `no` as the locale language code for Norsk Bokmål. - -### Fixed - -- Fixed error in COUPNCD() calculation for end of month [Issue #2116](https://github.com/PHPOffice/PhpSpreadsheet/issues/2116) - [PR #2119](https://github.com/PHPOffice/PhpSpreadsheet/pull/2119) -- Resolve default values when a null argument is passed for HLOOKUP(), VLOOKUP() and ADDRESS() functions [Issue #2120](https://github.com/PHPOffice/PhpSpreadsheet/issues/2120) - [PR #2121](https://github.com/PHPOffice/PhpSpreadsheet/pull/2121) -- Fixed incorrect R1C1 to A1 subtraction formula conversion (`R[-2]C-R[2]C`) [Issue #2076](https://github.com/PHPOffice/PhpSpreadsheet/pull/2076) [PR #2086](https://github.com/PHPOffice/PhpSpreadsheet/pull/2086) -- Correctly handle absolute A1 references when converting to R1C1 format [PR #2060](https://github.com/PHPOffice/PhpSpreadsheet/pull/2060) -- Correct default fill style for conditional without a pattern defined [Issue #2035](https://github.com/PHPOffice/PhpSpreadsheet/issues/2035) [PR #2050](https://github.com/PHPOffice/PhpSpreadsheet/pull/2050) -- Fixed issue where array key check for existince before accessing arrays in Xlsx.php [PR #1970](https://github.com/PHPOffice/PhpSpreadsheet/pull/1970) -- Fixed issue with quoted strings in number format mask rendered with toFormattedString() [Issue 1972#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1972) [PR #1978](https://github.com/PHPOffice/PhpSpreadsheet/pull/1978) -- Fixed issue with percentage formats in number format mask rendered with toFormattedString() [Issue 1929#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1929) [PR #1928](https://github.com/PHPOffice/PhpSpreadsheet/pull/1928) -- Fixed issue with _ spacing character in number format mask corrupting output from toFormattedString() [Issue 1924#](https://github.com/PHPOffice/PhpSpreadsheet/issues/1924) [PR #1927](https://github.com/PHPOffice/PhpSpreadsheet/pull/1927) -- Fix for [Issue #1887](https://github.com/PHPOffice/PhpSpreadsheet/issues/1887) - Lose Track of Selected Cells After Save -- Fixed issue with Xlsx@listWorksheetInfo not returning any data -- Fixed invalid arguments triggering mb_substr() error in LEFT(), MID() and RIGHT() text functions [Issue #640](https://github.com/PHPOffice/PhpSpreadsheet/issues/640) -- Fix for [Issue #1916](https://github.com/PHPOffice/PhpSpreadsheet/issues/1916) - Invalid signature check for XML files -- Fix change in `Font::setSize()` behavior for PHP8 [PR #2100](https://github.com/PHPOffice/PhpSpreadsheet/pull/2100) - -## 1.17.1 - 2021-03-01 - -### Added - -- Implementation of the Excel `AVERAGEIFS()` functions as part of a restructuring of Database functions and Conditional Statistical functions. -- Support for date values and percentages in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1875](https://github.com/PHPOffice/PhpSpreadsheet/pull/1875) -- Support for booleans, and for wildcard text search in query parameters for Database functions, and the IF expressions in functions like COUNTIF() and AVERAGEIF(). [#1876](https://github.com/PHPOffice/PhpSpreadsheet/pull/1876) -- Implemented DataBar for conditional formatting in Xlsx, providing read/write and creation of (type, value, direction, fills, border, axis position, color settings) as DataBar options in Excel. [#1754](https://github.com/PHPOffice/PhpSpreadsheet/pull/1754) -- Alignment for ODS Writer [#1796](https://github.com/PHPOffice/PhpSpreadsheet/issues/1796) -- Basic implementation of the PERMUTATIONA() Statistical Function - -### Changed - -- Formula functions that previously called PHP functions directly are now processed through the Excel Functions classes; resolving issues with PHP8 stricter typing. [#1789](https://github.com/PHPOffice/PhpSpreadsheet/issues/1789) - - The following MathTrig functions are affected: - `ABS()`, `ACOS()`, `ACOSH()`, `ASIN()`, `ASINH()`, `ATAN()`, `ATANH()`, - `COS()`, `COSH()`, `DEGREES()` (rad2deg), `EXP()`, `LN()` (log), `LOG10()`, - `RADIANS()` (deg2rad), `SIN()`, `SINH()`, `SQRT()`, `TAN()`, `TANH()`. - - One TextData function is also affected: `REPT()` (str_repeat). -- `formatAsDate` correctly matches language metadata, reverting c55272e -- Formulae that previously crashed on sub function call returning excel error value now return said value. - The following functions are affected `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`, - `AMORDEGRC()`. -- Adapt some function error return value to match excel's error. - The following functions are affected `PPMT()`, `IPMT()`. - -### Deprecated - -- Calling many of the Excel formula functions directly rather than through the Calculation Engine. - - The logic for these Functions is now being moved out of the categorised `Database`, `DateTime`, `Engineering`, `Financial`, `Logical`, `LookupRef`, `MathTrig`, `Statistical`, `TextData` and `Web` classes into small, dedicated classes for individual functions or related groups of functions. - - This makes the logic in these classes easier to maintain; and will reduce the memory footprint required to execute formulae when calling these functions. - -### Removed - -- Nothing. - -### Fixed - -- Avoid Duplicate Titles When Reading Multiple HTML Files.[Issue #1823](https://github.com/PHPOffice/PhpSpreadsheet/issues/1823) [PR #1829](https://github.com/PHPOffice/PhpSpreadsheet/pull/1829) -- Fixed issue with Worksheet's `getCell()` method when trying to get a cell by defined name. [#1858](https://github.com/PHPOffice/PhpSpreadsheet/issues/1858) -- Fix possible endless loop in NumberFormat Masks [#1792](https://github.com/PHPOffice/PhpSpreadsheet/issues/1792) -- Fix problem resulting from literal dot inside quotes in number format masks [PR #1830](https://github.com/PHPOffice/PhpSpreadsheet/pull/1830) -- Resolve Google Sheets Xlsx charts issue. Google Sheets uses oneCellAnchor positioning and does not include *Cache values in the exported Xlsx [PR #1761](https://github.com/PHPOffice/PhpSpreadsheet/pull/1761) -- Fix for Xlsx Chart axis titles mapping to correct X or Y axis label when only one is present [PR #1760](https://github.com/PHPOffice/PhpSpreadsheet/pull/1760) -- Fix For Null Exception on ODS Read of Page Settings. [#1772](https://github.com/PHPOffice/PhpSpreadsheet/issues/1772) -- Fix Xlsx reader overriding manually set number format with builtin number format [PR #1805](https://github.com/PHPOffice/PhpSpreadsheet/pull/1805) -- Fix Xlsx reader cell alignment [PR #1710](https://github.com/PHPOffice/PhpSpreadsheet/pull/1710) -- Fix for not yet implemented data-types in Open Document writer [Issue #1674](https://github.com/PHPOffice/PhpSpreadsheet/issues/1674) -- Fix XLSX reader when having a corrupt numeric cell data type [PR #1664](https://github.com/phpoffice/phpspreadsheet/pull/1664) -- Fix on `CUMPRINC()`, `CUMIPMT()`, `AMORLINC()`, `AMORDEGRC()` usage. When those functions called one of `YEARFRAC()`, `PPMT()`, `IPMT()` and they would get back an error value (represented as a string), trying to use numeral operands (`+`, `/`, `-`, `*`) on said return value and a number (`float or `int`) would fail. - -## 1.16.0 - 2020-12-31 - -### Added - -- CSV Reader - Best Guess for Encoding, and Handle Null-string Escape [#1647](https://github.com/PHPOffice/PhpSpreadsheet/issues/1647) - -### Changed - -- Updated the CONVERT() function to support all current MS Excel categories and Units of Measure. - -### Deprecated - -- All Excel Function implementations in `Calculation\Database`, `Calculation\DateTime`, `Calculation\Engineering`, `Calculation\Financial`, `Calculation\Logical`, `Calculation\LookupRef`, `Calculation\MathTrig`, `Calculation\Statistical`, `Calculation\TextData` and `Calculation\Web` have been moved to dedicated classes for individual functions or groups of related functions. See the docblocks against all the deprecated methods for details of the new methods to call instead. At some point, these old classes will be deleted. - -### Removed - -- Nothing. - -### Fixed - -- Fixed issue with absolute path in worksheets' Target [PR #1769](https://github.com/PHPOffice/PhpSpreadsheet/pull/1769) -- Fix for Xls Reader when SST has a bad length [#1592](https://github.com/PHPOffice/PhpSpreadsheet/issues/1592) -- Resolve Xlsx loader issue whe hyperlinks don't have a destination -- Resolve issues when printer settings resources IDs clash with drawing IDs -- Resolve issue with SLK long filenames [#1612](https://github.com/PHPOffice/PhpSpreadsheet/issues/1612) -- ROUNDUP and ROUNDDOWN return incorrect results for values of 0 [#1627](https://github.com/phpoffice/phpspreadsheet/pull/1627) -- Apply Column and Row Styles to Existing Cells [#1712](https://github.com/PHPOffice/PhpSpreadsheet/issues/1712) [PR #1721](https://github.com/PHPOffice/PhpSpreadsheet/pull/1721) -- Resolve issues with defined names where worksheet doesn't exist (#1686)[https://github.com/PHPOffice/PhpSpreadsheet/issues/1686] and [#1723](https://github.com/PHPOffice/PhpSpreadsheet/issues/1723) - [PR #1742](https://github.com/PHPOffice/PhpSpreadsheet/pull/1742) -- Fix for issue [#1735](https://github.com/PHPOffice/PhpSpreadsheet/issues/1735) Incorrect activeSheetIndex after RemoveSheetByIndex - [PR #1743](https://github.com/PHPOffice/PhpSpreadsheet/pull/1743) -- Ensure that the list of shared formulae is maintained when an xlsx file is chunked with readFilter[Issue #169](https://github.com/PHPOffice/PhpSpreadsheet/issues/1669). -- Fix for notice during accessing "cached magnification factor" offset [#1354](https://github.com/PHPOffice/PhpSpreadsheet/pull/1354) -- Fix compatibility with ext-gd on php 8 - -### Security Fix (CVE-2020-7776) - -- Prevent XSS through cell comments in the HTML Writer. - -## 1.15.0 - 2020-10-11 - -### Added - -- Implemented Page Order for Xlsx and Xls Readers, and provided Page Settings (Orientation, Scale, Horizontal/Vertical Centering, Page Order, Margins) support for Ods, Gnumeric and Xls Readers [#1559](https://github.com/PHPOffice/PhpSpreadsheet/pull/1559) -- Implementation of the Excel `LOGNORM.DIST()`, `NORM.S.DIST()`, `GAMMA()` and `GAUSS()` functions. [#1588](https://github.com/PHPOffice/PhpSpreadsheet/pull/1588) -- Named formula implementation, and improved handling of Defined Names generally [#1535](https://github.com/PHPOffice/PhpSpreadsheet/pull/1535) - - Defined Names are now case-insensitive - - Distinction between named ranges and named formulae - - Correct handling of union and intersection operators in named ranges - - Correct evaluation of named range operators in calculations - - fix resolution of relative named range values in the calculation engine; previously all named range values had been treated as absolute. - - Calculation support for named formulae - - Support for nested ranges and formulae (named ranges and formulae that reference other named ranges/formulae) in calculations - - Introduction of a helper to convert address formats between R1C1 and A1 (and the reverse) - - Proper support for both named ranges and named formulae in all appropriate Readers - - **Xlsx** (Previously only simple named ranges were supported) - - **Xls** (Previously only simple named ranges were supported) - - **Gnumeric** (Previously neither named ranges nor formulae were supported) - - **Ods** (Previously neither named ranges nor formulae were supported) - - **Xml** (Previously neither named ranges nor formulae were supported) - - Proper support for named ranges and named formulae in all appropriate Writers - - **Xlsx** (Previously only simple named ranges were supported) - - **Xls** (Previously neither named ranges nor formulae were supported) - Still not supported, but some parser issues resolved that previously failed to differentiate between a defined name and a function name - - **Ods** (Previously neither named ranges nor formulae were supported) -- Support for PHP 8.0 - -### Changed - -- Improve Coverage for ODS Reader [#1545](https://github.com/phpoffice/phpspreadsheet/pull/1545) -- Named formula implementation, and improved handling of Defined Names generally [#1535](https://github.com/PHPOffice/PhpSpreadsheet/pull/1535) -- fix resolution of relative named range values in the calculation engine; previously all named range values had been treated as absolute. -- Drop $this->spreadSheet null check from Xlsx Writer [#1646](https://github.com/phpoffice/phpspreadsheet/pull/1646) -- Improving Coverage for Excel2003 XML Reader [#1557](https://github.com/phpoffice/phpspreadsheet/pull/1557) - -### Deprecated - -- **IMPORTANT NOTE:** This Introduces a **BC break** in the handling of named ranges. Previously, a named range cell reference of `B2` would be treated identically to a named range cell reference of `$B2` or `B$2` or `$B$2` because the calculation engine treated then all as absolute references. These changes "fix" that, so the calculation engine now handles relative references in named ranges correctly. - This change that resolves previously incorrect behaviour in the calculation may affect users who have dynamically defined named ranges using relative references when they should have used absolute references. - -### Removed - -- Nothing. - -### Fixed - -- PrintArea causes exception [#1544](https://github.com/phpoffice/phpspreadsheet/pull/1544) -- Calculation/DateTime Failure With PHP8 [#1661](https://github.com/phpoffice/phpspreadsheet/pull/1661) -- Reader/Gnumeric Failure with PHP8 [#1662](https://github.com/phpoffice/phpspreadsheet/pull/1662) -- ReverseSort bug, exposed but not caused by PHP8 [#1660](https://github.com/phpoffice/phpspreadsheet/pull/1660) -- Bug setting Superscript/Subscript to false [#1567](https://github.com/phpoffice/phpspreadsheet/pull/1567) - -## 1.14.1 - 2020-07-19 - -### Added - -- nothing - -### Fixed - -- WEBSERVICE is HTTP client agnostic and must be configured via `Settings::setHttpClient()` [#1562](https://github.com/PHPOffice/PhpSpreadsheet/issues/1562) -- Borders were not complete on rowspanned columns using HTML reader [#1473](https://github.com/PHPOffice/PhpSpreadsheet/pull/1473) - -### Changed - -## 1.14.0 - 2020-06-29 - -### Added - -- Add support for IFS() logical function [#1442](https://github.com/PHPOffice/PhpSpreadsheet/pull/1442) -- Add Cell Address Helper to provide conversions between the R1C1 and A1 address formats [#1558](https://github.com/PHPOffice/PhpSpreadsheet/pull/1558) -- Add ability to edit Html/Pdf before saving [#1499](https://github.com/PHPOffice/PhpSpreadsheet/pull/1499) -- Add ability to set codepage explicitly for BIFF5 [#1018](https://github.com/PHPOffice/PhpSpreadsheet/issues/1018) -- Added support for the WEBSERVICE function [#1409](https://github.com/PHPOffice/PhpSpreadsheet/pull/1409) - -### Fixed - -- Resolve evaluation of utf-8 named ranges in calculation engine [#1522](https://github.com/PHPOffice/PhpSpreadsheet/pull/1522) -- Fix HLOOKUP on single row [#1512](https://github.com/PHPOffice/PhpSpreadsheet/pull/1512) -- Fix MATCH when comparing different numeric types [#1521](https://github.com/PHPOffice/PhpSpreadsheet/pull/1521) -- Fix exact MATCH on ranges with empty cells [#1520](https://github.com/PHPOffice/PhpSpreadsheet/pull/1520) -- Fix for Issue [#1516](https://github.com/PHPOffice/PhpSpreadsheet/issues/1516) (Cloning worksheet makes corrupted Xlsx) [#1530](https://github.com/PHPOffice/PhpSpreadsheet/pull/1530) -- Fix For Issue [#1509](https://github.com/PHPOffice/PhpSpreadsheet/issues/1509) (Can not set empty enclosure for CSV) [#1518](https://github.com/PHPOffice/PhpSpreadsheet/pull/1518) -- Fix for Issue [#1505](https://github.com/PHPOffice/PhpSpreadsheet/issues/1505) (TypeError : Argument 4 passed to PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeAttributeIf() must be of the type string) [#1525](https://github.com/PHPOffice/PhpSpreadsheet/pull/1525) -- Fix for Issue [#1495](https://github.com/PHPOffice/PhpSpreadsheet/issues/1495) (Sheet index being changed when multiple sheets are used in formula) [#1500]((https://github.com/PHPOffice/PhpSpreadsheet/pull/1500)) -- Fix for Issue [#1533](https://github.com/PHPOffice/PhpSpreadsheet/issues/1533) (A reference to a cell containing a string starting with "#" leads to errors in the generated xlsx.) [#1534](https://github.com/PHPOffice/PhpSpreadsheet/pull/1534) -- Xls Writer - Correct Timestamp Bug [#1493](https://github.com/PHPOffice/PhpSpreadsheet/pull/1493) -- Don't ouput row and columns without any cells in HTML writer [#1235](https://github.com/PHPOffice/PhpSpreadsheet/issues/1235) - -## 1.13.0 - 2020-05-31 - -### 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) -- Support protection of worksheet by a specific hash algorithm [#1485](https://github.com/PHPOffice/PhpSpreadsheet/pull/1485) - -### 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) -- Fix incorrect behaviour when saving XLSX file with drawings [#1462](https://github.com/PHPOffice/PhpSpreadsheet/pull/1462), -- Fix Crash while trying setting a cell the value "123456\n" [#1476](https://github.com/PHPOffice/PhpSpreadsheet/pull/1481) -- Improved DATEDIF() function and reduced errors for Y and YM units [#1466](https://github.com/PHPOffice/PhpSpreadsheet/pull/1466) -- Stricter typing for mergeCells [#1494](https://github.com/PHPOffice/PhpSpreadsheet/pull/1494) - -### 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 - -### Added - -- Improved the ARABIC function to also handle short-hand roman numerals -- Added support for the FLOOR.MATH and FLOOR.PRECISE functions [#1351](https://github.com/PHPOffice/PhpSpreadsheet/pull/1351) - -### Fixed - -- Fix ROUNDUP and ROUNDDOWN for floating-point rounding error [#1404](https://github.com/PHPOffice/PhpSpreadsheet/pull/1404) -- Fix ROUNDUP and ROUNDDOWN for negative number [#1417](https://github.com/PHPOffice/PhpSpreadsheet/pull/1417) -- Fix loading styles from vmlDrawings when containing whitespace [#1347](https://github.com/PHPOffice/PhpSpreadsheet/issues/1347) -- Fix incorrect behavior when removing last row [#1365](https://github.com/PHPOffice/PhpSpreadsheet/pull/1365) -- MATCH with a static array should return the position of the found value based on the values submitted [#1332](https://github.com/PHPOffice/PhpSpreadsheet/pull/1332) -- Fix Xlsx Reader's handling of undefined fill color [#1353](https://github.com/PHPOffice/PhpSpreadsheet/pull/1353) - -## 1.11.0 - 2020-03-02 - -### Added - -- Added support for the BASE function -- Added support for the ARABIC function -- Conditionals - Extend Support for (NOT)CONTAINSBLANKS [#1278](https://github.com/PHPOffice/PhpSpreadsheet/pull/1278) - -### Fixed - -- Handle Error in Formula Processing Better for Xls [#1267](https://github.com/PHPOffice/PhpSpreadsheet/pull/1267) -- Handle ConditionalStyle NumberFormat When Reading Xlsx File [#1296](https://github.com/PHPOffice/PhpSpreadsheet/pull/1296) -- Fix Xlsx Writer's handling of decimal commas [#1282](https://github.com/PHPOffice/PhpSpreadsheet/pull/1282) -- Fix for issue by removing test code mistakenly left in [#1328](https://github.com/PHPOffice/PhpSpreadsheet/pull/1328) -- Fix for Xls writer wrong selected cells and active sheet [#1256](https://github.com/PHPOffice/PhpSpreadsheet/pull/1256) -- Fix active cell when freeze pane is used [#1323](https://github.com/PHPOffice/PhpSpreadsheet/pull/1323) -- Fix XLSX file loading with autofilter containing '$' [#1326](https://github.com/PHPOffice/PhpSpreadsheet/pull/1326) -- PHPDoc - Use `@return $this` for fluent methods [#1362](https://github.com/PHPOffice/PhpSpreadsheet/pull/1362) - -## 1.10.1 - 2019-12-02 - -### Changed - -- PHP 7.4 compatibility - -### Fixed - -- FLOOR() function accept negative number and negative significance [#1245](https://github.com/PHPOffice/PhpSpreadsheet/pull/1245) -- Correct column style even when using rowspan [#1249](https://github.com/PHPOffice/PhpSpreadsheet/pull/1249) -- Do not confuse defined names and cell refs [#1263](https://github.com/PHPOffice/PhpSpreadsheet/pull/1263) -- XLSX reader/writer keep decimal for floats with a zero decimal part [#1262](https://github.com/PHPOffice/PhpSpreadsheet/pull/1262) -- ODS writer prevent invalid numeric value if locale decimal separator is comma [#1268](https://github.com/PHPOffice/PhpSpreadsheet/pull/1268) -- Xlsx writer actually writes plotVisOnly and dispBlanksAs from chart properties [#1266](https://github.com/PHPOffice/PhpSpreadsheet/pull/1266) - -## 1.10.0 - 2019-11-18 - -### Changed - -- Change license from LGPL 2.1 to MIT [#140](https://github.com/PHPOffice/PhpSpreadsheet/issues/140) - -### Added - -- Implementation of IFNA() logical function -- Support "showZeros" worksheet option to change how Excel shows and handles "null" values returned from a calculation -- Allow HTML Reader to accept HTML as a string into an existing spreadsheet [#1212](https://github.com/PHPOffice/PhpSpreadsheet/pull/1212) - -### Fixed - -- IF implementation properly handles the value `#N/A` [#1165](https://github.com/PHPOffice/PhpSpreadsheet/pull/1165) -- Formula Parser: Wrong line count for stuff like "MyOtherSheet!A:D" [#1215](https://github.com/PHPOffice/PhpSpreadsheet/issues/1215) -- Call garbage collector after removing a column to prevent stale cached values -- Trying to remove a column that doesn't exist deletes the latest column -- Keep big integer as integer instead of lossely casting to float [#874](https://github.com/PHPOffice/PhpSpreadsheet/pull/874) -- Fix branch pruning handling of non boolean conditions [#1167](https://github.com/PHPOffice/PhpSpreadsheet/pull/1167) -- Fix ODS Reader when no DC namespace are defined [#1182](https://github.com/PHPOffice/PhpSpreadsheet/pull/1182) -- Fixed Functions->ifCondition for allowing <> and empty condition [#1206](https://github.com/PHPOffice/PhpSpreadsheet/pull/1206) -- Validate XIRR inputs and return correct error values [#1120](https://github.com/PHPOffice/PhpSpreadsheet/issues/1120) -- Allow to read xlsx files with exotic workbook names like "workbook2.xml" [#1183](https://github.com/PHPOffice/PhpSpreadsheet/pull/1183) - -## 1.9.0 - 2019-08-17 - -### Changed - -- Drop support for PHP 5.6 and 7.0, according to https://phpspreadsheet.readthedocs.io/en/latest/#php-version-support - -### Added - -- When <br> appears in a table cell, set the cell to wrap [#1071](https://github.com/PHPOffice/PhpSpreadsheet/issues/1071) and [#1070](https://github.com/PHPOffice/PhpSpreadsheet/pull/1070) -- Add MAXIFS, MINIFS, COUNTIFS and Remove MINIF, MAXIF [#1056](https://github.com/PHPOffice/PhpSpreadsheet/issues/1056) -- HLookup needs an ordered list even if range_lookup is set to false [#1055](https://github.com/PHPOffice/PhpSpreadsheet/issues/1055) and [#1076](https://github.com/PHPOffice/PhpSpreadsheet/pull/1076) -- Improve performance of IF function calls via ranch pruning to avoid resolution of every branches [#844](https://github.com/PHPOffice/PhpSpreadsheet/pull/844) -- MATCH function supports `*?~` Excel functionality, when match_type=0 [#1116](https://github.com/PHPOffice/PhpSpreadsheet/issues/1116) -- Allow HTML Reader to accept HTML as a string [#1136](https://github.com/PHPOffice/PhpSpreadsheet/pull/1136) - -### Fixed - -- Fix to AVERAGEIF() function when called with a third argument -- Eliminate duplicate fill none style entries [#1066](https://github.com/PHPOffice/PhpSpreadsheet/issues/1066) -- Fix number format masks containing literal (non-decimal point) dots [#1079](https://github.com/PHPOffice/PhpSpreadsheet/issues/1079) -- Fix number format masks containing named colours that were being misinterpreted as date formats; and add support for masks that fully replace the value with a full text string [#1009](https://github.com/PHPOffice/PhpSpreadsheet/issues/1009) -- Stricter-typed comparison testing in COUNTIF() and COUNTIFS() evaluation [#1046](https://github.com/PHPOffice/PhpSpreadsheet/issues/1046) -- COUPNUM should not return zero when settlement is in the last period [#1020](https://github.com/PHPOffice/PhpSpreadsheet/issues/1020) and [#1021](https://github.com/PHPOffice/PhpSpreadsheet/pull/1021) -- Fix handling of named ranges referencing sheets with spaces or "!" in their title -- Cover `getSheetByName()` with tests for name with quote and spaces [#739](https://github.com/PHPOffice/PhpSpreadsheet/issues/739) -- Best effort to support invalid colspan values in HTML reader - [#878](https://github.com/PHPOffice/PhpSpreadsheet/pull/878) -- Fixes incorrect rows deletion [#868](https://github.com/PHPOffice/PhpSpreadsheet/issues/868) -- MATCH function fix (value search by type, stop search when match_type=-1 and unordered element encountered) [#1116](https://github.com/PHPOffice/PhpSpreadsheet/issues/1116) -- Fix `getCalculatedValue()` error with more than two INDIRECT [#1115](https://github.com/PHPOffice/PhpSpreadsheet/pull/1115) -- Writer\Html did not hide columns [#985](https://github.com/PHPOffice/PhpSpreadsheet/pull/985) - -## 1.8.2 - 2019-07-08 - -### Fixed - -- Uncaught error when opening ods file and properties aren't defined [#1047](https://github.com/PHPOffice/PhpSpreadsheet/issues/1047) -- Xlsx Reader Cell datavalidations bug [#1052](https://github.com/PHPOffice/PhpSpreadsheet/pull/1052) - -## 1.8.1 - 2019-07-02 - -### Fixed - -- Allow nullable theme for Xlsx Style Reader class [#1043](https://github.com/PHPOffice/PhpSpreadsheet/issues/1043) - -## 1.8.0 - 2019-07-01 - -### Security Fix (CVE-2019-12331) - -- Detect double-encoded xml in the Security scanner, and reject as suspicious. -- This change also broadens the scope of the `libxml_disable_entity_loader` setting when reading XML-based formats, so that it is enabled while the xml is being parsed and not simply while it is loaded. - On some versions of PHP, this can cause problems because it is not thread-safe, and can affect other PHP scripts running on the same server. This flag is set to true when instantiating a loader, and back to its original setting when the Reader is no longer in scope, or manually unset. -- Provide a check to identify whether libxml_disable_entity_loader is thread-safe or not. - - `XmlScanner::threadSafeLibxmlDisableEntityLoaderAvailability()` -- Provide an option to disable the libxml_disable_entity_loader call through settings. This is not recommended as it reduces the security of the XML-based readers, and should only be used if you understand the consequences and have no other choice. - -### Added - -- Added support for the SWITCH function [#963](https://github.com/PHPOffice/PhpSpreadsheet/issues/963) and [#983](https://github.com/PHPOffice/PhpSpreadsheet/pull/983) -- Add accounting number format style [#974](https://github.com/PHPOffice/PhpSpreadsheet/pull/974) - -### Fixed - -- Whitelist `tsv` extension when opening CSV files [#429](https://github.com/PHPOffice/PhpSpreadsheet/issues/429) -- Fix a SUMIF warning with some versions of PHP when having different length of arrays provided as input [#873](https://github.com/PHPOffice/PhpSpreadsheet/pull/873) -- Fix incorrectly handled backslash-escaped space characters in number format - -## 1.7.0 - 2019-05-26 - -- Added support for inline styles in Html reader (borders, alignment, width, height) -- QuotedText cells no longer treated as formulae if the content begins with a `=` -- Clean handling for DDE in formulae - -### Fixed - -- Fix handling for escaped enclosures and new lines in CSV Separator Inference -- Fix MATCH an error was appearing when comparing strings against 0 (always true) -- Fix wrong calculation of highest column with specified row [#700](https://github.com/PHPOffice/PhpSpreadsheet/issues/700) -- Fix VLOOKUP -- Fix return type hint - -## 1.6.0 - 2019-01-02 - -### Added - -- Refactored Matrix Functions to use external Matrix library -- Possibility to specify custom colors of values for pie and donut charts [#768](https://github.com/PHPOffice/PhpSpreadsheet/pull/768) - -### Fixed - -- Improve XLSX parsing speed if no readFilter is applied [#772](https://github.com/PHPOffice/PhpSpreadsheet/issues/772) -- Fix column names if read filter calls in XLSX reader skip columns [#777](https://github.com/PHPOffice/PhpSpreadsheet/pull/777) -- XLSX reader can now ignore blank cells, using the setReadEmptyCells(false) method. [#810](https://github.com/PHPOffice/PhpSpreadsheet/issues/810) -- Fix LOOKUP function which was breaking on edge cases [#796](https://github.com/PHPOffice/PhpSpreadsheet/issues/796) -- Fix VLOOKUP with exact matches [#809](https://github.com/PHPOffice/PhpSpreadsheet/pull/809) -- Support COUNTIFS multiple arguments [#830](https://github.com/PHPOffice/PhpSpreadsheet/pull/830) -- Change `libxml_disable_entity_loader()` as shortly as possible [#819](https://github.com/PHPOffice/PhpSpreadsheet/pull/819) -- Improved memory usage and performance when loading large spreadsheets [#822](https://github.com/PHPOffice/PhpSpreadsheet/pull/822) -- Improved performance when loading large spreadsheets [#825](https://github.com/PHPOffice/PhpSpreadsheet/pull/825) -- Improved performance when loading large spreadsheets [#824](https://github.com/PHPOffice/PhpSpreadsheet/pull/824) -- Fix color from CSS when reading from HTML [#831](https://github.com/PHPOffice/PhpSpreadsheet/pull/831) -- Fix infinite loop when reading invalid ODS files [#832](https://github.com/PHPOffice/PhpSpreadsheet/pull/832) -- Fix time format for duration is incorrect [#666](https://github.com/PHPOffice/PhpSpreadsheet/pull/666) -- Fix iconv unsupported `//IGNORE//TRANSLIT` on IBM i [#791](https://github.com/PHPOffice/PhpSpreadsheet/issues/791) - -### Changed - -- `master` is the new default branch, `develop` does not exist anymore - -## 1.5.2 - 2018-11-25 - -### Security - -- Improvements to the design of the XML Security Scanner [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771) - -## 1.5.1 - 2018-11-20 - -### Security - -- Fix and improve XXE security scanning for XML-based and HTML Readers [#771](https://github.com/PHPOffice/PhpSpreadsheet/issues/771) - -### Added - -- Support page margin in mPDF [#750](https://github.com/PHPOffice/PhpSpreadsheet/issues/750) - -### Fixed - -- Support numeric condition in SUMIF, SUMIFS, AVERAGEIF, COUNTIF, MAXIF and MINIF [#683](https://github.com/PHPOffice/PhpSpreadsheet/issues/683) -- SUMIFS containing multiple conditions [#704](https://github.com/PHPOffice/PhpSpreadsheet/issues/704) -- Csv reader avoid notice when the file is empty [#743](https://github.com/PHPOffice/PhpSpreadsheet/pull/743) -- Fix print area parser for XLSX reader [#734](https://github.com/PHPOffice/PhpSpreadsheet/pull/734) -- Support overriding `DefaultValueBinder::dataTypeForValue()` without overriding `DefaultValueBinder::bindValue()` [#735](https://github.com/PHPOffice/PhpSpreadsheet/pull/735) -- Mpdf export can exceed pcre.backtrack_limit [#637](https://github.com/PHPOffice/PhpSpreadsheet/issues/637) -- Fix index overflow on data values array [#748](https://github.com/PHPOffice/PhpSpreadsheet/pull/748) - -## 1.5.0 - 2018-10-21 - -### Added - -- PHP 7.3 support -- Add the DAYS() function [#594](https://github.com/PHPOffice/PhpSpreadsheet/pull/594) +## [Unreleased] ### Fixed -- Sheet title can contain exclamation mark [#325](https://github.com/PHPOffice/PhpSpreadsheet/issues/325) -- Xls file cause the exception during open by Xls reader [#402](https://github.com/PHPOffice/PhpSpreadsheet/issues/402) -- Skip non numeric value in SUMIF [#618](https://github.com/PHPOffice/PhpSpreadsheet/pull/618) -- OFFSET should allow omitted height and width [#561](https://github.com/PHPOffice/PhpSpreadsheet/issues/561) -- Correctly determine delimiter when CSV contains line breaks inside enclosures [#716](https://github.com/PHPOffice/PhpSpreadsheet/issues/716) +- Sheet title can contain exclamation mark - [#325](https://github.com/PHPOffice/PhpSpreadsheet/issues/325) +- Xls file cause the exception during open by Xls reader - [#402](https://github.com/PHPOffice/PhpSpreadsheet/issues/402) +- Skip non numeric value in SUMIF - [#618](https://github.com/PHPOffice/PhpSpreadsheet/pull/618) -## 1.4.1 - 2018-09-30 +## [1.4.1] - 2018-09-30 ### Fixed -- Remove locale from formatting string [#644](https://github.com/PHPOffice/PhpSpreadsheet/pull/644) -- Allow iterators to go out of bounds with prev [#587](https://github.com/PHPOffice/PhpSpreadsheet/issues/587) -- Fix warning when reading xlsx without styles [#631](https://github.com/PHPOffice/PhpSpreadsheet/pull/631) -- Fix broken sample links on windows due to $baseDir having backslash [#653](https://github.com/PHPOffice/PhpSpreadsheet/pull/653) +- Remove locale from formatting string - [#644](https://github.com/PHPOffice/PhpSpreadsheet/pull/644) +- Allow iterators to go out of bounds with prev - [#587](https://github.com/PHPOffice/PhpSpreadsheet/issues/587) +- Fix warning when reading xlsx without styles - [#631](https://github.com/PHPOffice/PhpSpreadsheet/pull/631) +- Fix broken sample links on windows due to $baseDir having backslash - [#653](https://github.com/PHPOffice/PhpSpreadsheet/pull/653) -## 1.4.0 - 2018-08-06 +## [1.4.0] - 2018-08-06 ### Added -- Add excel function EXACT(value1, value2) support [#595](https://github.com/PHPOffice/PhpSpreadsheet/pull/595) -- Support workbook view attributes for Xlsx format [#523](https://github.com/PHPOffice/PhpSpreadsheet/issues/523) -- Read and write hyperlink for drawing image [#490](https://github.com/PHPOffice/PhpSpreadsheet/pull/490) +- Add excel function EXACT(value1, value2) support - [#595](https://github.com/PHPOffice/PhpSpreadsheet/pull/595) +- Support workbook view attributes for Xlsx format - [#523](https://github.com/PHPOffice/PhpSpreadsheet/issues/523) +- Read and write hyperlink for drawing image - [#490](https://github.com/PHPOffice/PhpSpreadsheet/pull/490) - Added calculation engine support for the new bitwise functions that were added in MS Excel 2013 - BITAND() Returns a Bitwise 'And' of two numbers - BITOR() Returns a Bitwise 'Or' of two number @@ -1768,102 +77,102 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi ### Fixed - Fix ISFORMULA() function to work with a cell reference to another worksheet -- Xlsx reader crashed when reading a file with workbook protection [#553](https://github.com/PHPOffice/PhpSpreadsheet/pull/553) -- Cell formats with escaped spaces were causing incorrect date formatting [#557](https://github.com/PHPOffice/PhpSpreadsheet/issues/557) -- Could not open CSV file containing HTML fragment [#564](https://github.com/PHPOffice/PhpSpreadsheet/issues/564) -- Exclude the vendor folder in migration [#481](https://github.com/PHPOffice/PhpSpreadsheet/issues/481) +- Xlsx reader crashed when reading a file with workbook protection - [#553](https://github.com/PHPOffice/PhpSpreadsheet/pull/553) +- Cell formats with escaped spaces were causing incorrect date formatting - [#557](https://github.com/PHPOffice/PhpSpreadsheet/issues/557) +- Could not open CSV file containing HTML fragment - [#564](https://github.com/PHPOffice/PhpSpreadsheet/issues/564) +- Exclude the vendor folder in migration - [#481](https://github.com/PHPOffice/PhpSpreadsheet/issues/481) - Chained operations on cell ranges involving borders operated on last cell only [#428](https://github.com/PHPOffice/PhpSpreadsheet/issues/428) - Avoid memory exhaustion when cloning worksheet with a drawing [#437](https://github.com/PHPOffice/PhpSpreadsheet/issues/437) - Migration tool keep variables containing $PHPExcel untouched [#598](https://github.com/PHPOffice/PhpSpreadsheet/issues/598) - Rowspans/colspans were incorrect when adding worksheet using loadIntoExisting [#619](https://github.com/PHPOffice/PhpSpreadsheet/issues/619) -## 1.3.1 - 2018-06-12 +## [1.3.1] - 2018-06-12 ### Fixed -- Ranges across Z and AA columns incorrectly threw an exception [#545](https://github.com/PHPOffice/PhpSpreadsheet/issues/545) +- Ranges across Z and AA columns incorrectly threw an exception - [#545](https://github.com/PHPOffice/PhpSpreadsheet/issues/545) -## 1.3.0 - 2018-06-10 +## [1.3.0] - 2018-06-10 ### Added -- Support to read Xlsm templates with form elements, macros, printer settings, protected elements and back compatibility drawing, and save result without losing important elements of document [#435](https://github.com/PHPOffice/PhpSpreadsheet/issues/435) -- Expose sheet title maximum length as `Worksheet::SHEET_TITLE_MAXIMUM_LENGTH` [#482](https://github.com/PHPOffice/PhpSpreadsheet/issues/482) -- Allow escape character to be set in CSV reader [#492](https://github.com/PHPOffice/PhpSpreadsheet/issues/492) +- Support to read Xlsm templates with form elements, macros, printer settings, protected elements and back compatibility drawing, and save result without losing important elements of document - [#435](https://github.com/PHPOffice/PhpSpreadsheet/issues/435) +- Expose sheet title maximum length as `Worksheet::SHEET_TITLE_MAXIMUM_LENGTH` - [#482](https://github.com/PHPOffice/PhpSpreadsheet/issues/482) +- Allow escape character to be set in CSV reader – [#492](https://github.com/PHPOffice/PhpSpreadsheet/issues/492) ### Fixed -- Subtotal 9 in a group that has other subtotals 9 exclude the totals of the other subtotals in the range [#332](https://github.com/PHPOffice/PhpSpreadsheet/issues/332) -- `Helper\Html` support UTF-8 HTML input [#444](https://github.com/PHPOffice/PhpSpreadsheet/issues/444) -- Xlsx loaded an extra empty comment for each real comment [#375](https://github.com/PHPOffice/PhpSpreadsheet/issues/375) -- Xlsx reader do not read rows and columns filtered out in readFilter at all [#370](https://github.com/PHPOffice/PhpSpreadsheet/issues/370) -- Make newer Excel versions properly recalculate formulas on document open [#456](https://github.com/PHPOffice/PhpSpreadsheet/issues/456) -- `Coordinate::extractAllCellReferencesInRange()` throws an exception for an invalid range [#519](https://github.com/PHPOffice/PhpSpreadsheet/issues/519) -- Fixed parsing of conditionals in COUNTIF functions [#526](https://github.com/PHPOffice/PhpSpreadsheet/issues/526) -- Corruption errors for saved Xlsx docs with frozen panes [#532](https://github.com/PHPOffice/PhpSpreadsheet/issues/532) +- Subtotal 9 in a group that has other subtotals 9 exclude the totals of the other subtotals in the range - [#332](https://github.com/PHPOffice/PhpSpreadsheet/issues/332) +- `Helper\Html` support UTF-8 HTML input - [#444](https://github.com/PHPOffice/PhpSpreadsheet/issues/444) +- Xlsx loaded an extra empty comment for each real comment - [#375](https://github.com/PHPOffice/PhpSpreadsheet/issues/375) +- Xlsx reader do not read rows and columns filtered out in readFilter at all - [#370](https://github.com/PHPOffice/PhpSpreadsheet/issues/370) +- Make newer Excel versions properly recalculate formulas on document open - [#456](https://github.com/PHPOffice/PhpSpreadsheet/issues/456) +- `Coordinate::extractAllCellReferencesInRange()` throws an exception for an invalid range – [#519](https://github.com/PHPOffice/PhpSpreadsheet/issues/519) +- Fixed parsing of conditionals in COUNTIF functions - [#526](https://github.com/PHPOffice/PhpSpreadsheet/issues/526) +- Corruption errors for saved Xlsx docs with frozen panes - [#532](https://github.com/PHPOffice/PhpSpreadsheet/issues/532) -## 1.2.1 - 2018-04-10 +## [1.2.1] - 2018-04-10 ### Fixed -- Plain text and richtext mixed in same cell can be read [#442](https://github.com/PHPOffice/PhpSpreadsheet/issues/442) +- Plain text and richtext mixed in same cell can be read - [#442](https://github.com/PHPOffice/PhpSpreadsheet/issues/442) -## 1.2.0 - 2018-03-04 +## [1.2.0] - 2018-03-04 ### Added -- HTML writer creates a generator meta tag [#312](https://github.com/PHPOffice/PhpSpreadsheet/issues/312) -- Support invalid zoom value in XLSX format [#350](https://github.com/PHPOffice/PhpSpreadsheet/pull/350) -- Support for `_xlfn.` prefixed functions and `ISFORMULA`, `MODE.SNGL`, `STDEV.S`, `STDEV.P` [#390](https://github.com/PHPOffice/PhpSpreadsheet/pull/390) +- HTML writer creates a generator meta tag - [#312](https://github.com/PHPOffice/PhpSpreadsheet/issues/312) +- Support invalid zoom value in XLSX format - [#350](https://github.com/PHPOffice/PhpSpreadsheet/pull/350) +- Support for `_xlfn.` prefixed functions and `ISFORMULA`, `MODE.SNGL`, `STDEV.S`, `STDEV.P` - [#390](https://github.com/PHPOffice/PhpSpreadsheet/pull/390) ### Fixed -- Avoid potentially unsupported PSR-16 cache keys [#354](https://github.com/PHPOffice/PhpSpreadsheet/issues/354) -- Check for MIME type to know if CSV reader can read a file [#167](https://github.com/PHPOffice/PhpSpreadsheet/issues/167) -- Use proper € symbol for currency format [#379](https://github.com/PHPOffice/PhpSpreadsheet/pull/379) -- Read printing area correctly when skipping some sheets [#371](https://github.com/PHPOffice/PhpSpreadsheet/issues/371) -- Avoid incorrectly overwriting calculated value type [#394](https://github.com/PHPOffice/PhpSpreadsheet/issues/394) -- Select correct cell when calling freezePane [#389](https://github.com/PHPOffice/PhpSpreadsheet/issues/389) -- `setStrikethrough()` did not set the font [#403](https://github.com/PHPOffice/PhpSpreadsheet/issues/403) +- Avoid potentially unsupported PSR-16 cache keys - [#354](https://github.com/PHPOffice/PhpSpreadsheet/issues/354) +- Check for MIME type to know if CSV reader can read a file - [#167](https://github.com/PHPOffice/PhpSpreadsheet/issues/167) +- Use proper € symbol for currency format - [#379](https://github.com/PHPOffice/PhpSpreadsheet/pull/379) +- Read printing area correctly when skipping some sheets - [#371](https://github.com/PHPOffice/PhpSpreadsheet/issues/371) +- Avoid incorrectly overwriting calculated value type - [#394](https://github.com/PHPOffice/PhpSpreadsheet/issues/394) +- Select correct cell when calling freezePane - [#389](https://github.com/PHPOffice/PhpSpreadsheet/issues/389) +- `setStrikethrough()` did not set the font - [#403](https://github.com/PHPOffice/PhpSpreadsheet/issues/403) -## 1.1.0 - 2018-01-28 +## [1.1.0] - 2018-01-28 ### Added - Support for PHP 7.2 -- Support cell comments in HTML writer and reader [#308](https://github.com/PHPOffice/PhpSpreadsheet/issues/308) -- Option to stop at a conditional styling, if it matches (only XLSX format) [#292](https://github.com/PHPOffice/PhpSpreadsheet/pull/292) -- Support for line width for data series when rendering Xlsx [#329](https://github.com/PHPOffice/PhpSpreadsheet/pull/329) +- Support cell comments in HTML writer and reader - [#308](https://github.com/PHPOffice/PhpSpreadsheet/issues/308) +- Option to stop at a conditional styling, if it matches (only XLSX format) - [#292](https://github.com/PHPOffice/PhpSpreadsheet/pull/292) +- Support for line width for data series when rendering Xlsx - [#329](https://github.com/PHPOffice/PhpSpreadsheet/pull/329) ### Fixed -- Better auto-detection of CSV separators [#305](https://github.com/PHPOffice/PhpSpreadsheet/issues/305) -- Support for shape style ending with `;` [#304](https://github.com/PHPOffice/PhpSpreadsheet/issues/304) -- Freeze Panes takes wrong coordinates for XLSX [#322](https://github.com/PHPOffice/PhpSpreadsheet/issues/322) -- `COLUMNS` and `ROWS` functions crashed in some cases [#336](https://github.com/PHPOffice/PhpSpreadsheet/issues/336) -- Support XML file without styles [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331) +- Better auto-detection of CSV separators - [#305](https://github.com/PHPOffice/PhpSpreadsheet/issues/305) +- Support for shape style ending with `;` - [#304](https://github.com/PHPOffice/PhpSpreadsheet/issues/304) +- Freeze Panes takes wrong coordinates for XLSX - [#322](https://github.com/PHPOffice/PhpSpreadsheet/issues/322) +- `COLUMNS` and `ROWS` functions crashed in some cases - [#336](https://github.com/PHPOffice/PhpSpreadsheet/issues/336) +- Support XML file without styles - [#331](https://github.com/PHPOffice/PhpSpreadsheet/pull/331) - Cell coordinates which are already a range cause an exception [#319](https://github.com/PHPOffice/PhpSpreadsheet/issues/319) -## 1.0.0 - 2017-12-25 +## [1.0.0] - 2017-12-25 ### Added -- Support to write merged cells in ODS format [#287](https://github.com/PHPOffice/PhpSpreadsheet/issues/287) -- Able to set the `topLeftCell` in freeze panes [#261](https://github.com/PHPOffice/PhpSpreadsheet/pull/261) +- Support to write merged cells in ODS format - [#287](https://github.com/PHPOffice/PhpSpreadsheet/issues/287) +- Able to set the `topLeftCell` in freeze panes - [#261](https://github.com/PHPOffice/PhpSpreadsheet/pull/261) - Support `DateTimeImmutable` as cell value - Support migration of prefixed classes ### Fixed -- Can read very small HTML files [#194](https://github.com/PHPOffice/PhpSpreadsheet/issues/194) -- Written DataValidation was corrupted [#290](https://github.com/PHPOffice/PhpSpreadsheet/issues/290) -- Date format compatible with both LibreOffice and Excel [#298](https://github.com/PHPOffice/PhpSpreadsheet/issues/298) +- Can read very small HTML files - [#194](https://github.com/PHPOffice/PhpSpreadsheet/issues/194) +- Written DataValidation was corrupted - [#290](https://github.com/PHPOffice/PhpSpreadsheet/issues/290) +- Date format compatible with both LibreOffice and Excel - [#298](https://github.com/PHPOffice/PhpSpreadsheet/issues/298) ### BREAKING CHANGE - Constant `TYPE_DOUGHTNUTCHART` is now `TYPE_DOUGHNUTCHART`. -## 1.0.0-beta2 - 2017-11-26 +## [1.0.0-beta2] - 2017-11-26 ### Added @@ -1876,13 +185,13 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Merge data-validations to reduce written worksheet size - @billblume [#131](https://github.com/PHPOffice/PhpSpreadSheet/issues/131) - Throws exception if a XML file is invalid - @GreatHumorist [#222](https://github.com/PHPOffice/PhpSpreadsheet/pull/222) -- Upgrade to mPDF 7.0+ [#144](https://github.com/PHPOffice/PhpSpreadsheet/issues/144) +- Upgrade to mPDF 7.0+ - [#144](https://github.com/PHPOffice/PhpSpreadsheet/issues/144) ### Fixed -- Control characters in cell values are automatically escaped [#212](https://github.com/PHPOffice/PhpSpreadsheet/issues/212) +- Control characters in cell values are automatically escaped - [#212](https://github.com/PHPOffice/PhpSpreadsheet/issues/212) - Prevent color changing when copy/pasting xls files written by PhpSpreadsheet to another file - @al-lala [#218](https://github.com/PHPOffice/PhpSpreadsheet/issues/218) -- Add cell reference automatic when there is no cell reference('r' attribute) in Xlsx file. - @GreatHumorist [#225](https://github.com/PHPOffice/PhpSpreadsheet/pull/225) Refer to [#201](https://github.com/PHPOffice/PhpSpreadsheet/issues/201) +- Add cell reference automatic when there is no cell reference('r' attribute) in Xlsx file. - @GreatHumorist [#225](https://github.com/PHPOffice/PhpSpreadsheet/pull/225) Refer to [issue#201](https://github.com/PHPOffice/PhpSpreadsheet/issues/201) - `Reader\Xlsx::getFromZipArchive()` function return false if the zip entry could not be located. - @anton-harvey [#268](https://github.com/PHPOffice/PhpSpreadsheet/pull/268) ### BREAKING CHANGE @@ -1901,7 +210,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - `PhpSpreadsheet\Style` => `PhpSpreadsheet\Style\Style` - `PhpSpreadsheet\Worksheet` => `PhpSpreadsheet\Worksheet\Worksheet` -## 1.0.0-beta - 2017-08-17 +## [1.0.0-beta] - 2017-08-17 ### Added @@ -1913,7 +222,7 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi ### Changed -- Start following [SemVer](https://semver.org) properly. +- Start following [SemVer](http://semver.org) properly. ### Fixed @@ -1921,7 +230,6 @@ Note that this will be the last 1.x branch release before the 2.x release. We wi - Ignore inlineStr type if formula element exists - @ncrypthic [#570](https://github.com/PHPOffice/PHPExcel/issues/570) - Excel 2007 Reader freezes because of conditional formatting - @rentalhost [#575](https://github.com/PHPOffice/PHPExcel/issues/575) - Readers will now parse files containing worksheet titles over 31 characters [#176](https://github.com/PHPOffice/PhpSpreadsheet/pull/176) -- Fixed PHP8 deprecation warning for libxml_disable_entity_loader() [#1625](https://github.com/phpoffice/phpspreadsheet/pull/1625) ### General @@ -1944,6 +252,3 @@ For a comprehensive list of all class changes, and a semi-automated migration pa ## Previous versions of PHPExcel The changelog for the project when it was called PHPExcel is [still available](./CHANGELOG.PHPExcel.md). - -### Changed -- Replace ezyang/htmlpurifier (LGPL2.1) with voku/anti-xss (MIT) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88a03398f2..62f0772166 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,48 +2,10 @@ If you would like to contribute, here are some notes and guidelines: - - All new development should be on feature/fix branches, which are then merged to the `master` branch once stable and approved; so the `master` branch is always the most up-to-date, working code - - If you are going to submit a pull request, please fork from `master`, and submit your pull request back as a fix/feature branch referencing the GitHub issue number - - Install (development) dependencies by running `composer install` inside your PhpSpreadsheet clone. - - The code must work with all PHP versions that we support. - - You can call `composer versions` to test version compatibility. - - Code style should be maintained. - - `composer style` will identify any issues with Coding Style. - - `composer fix` will fix most issues with Coding Style. - - All code changes must be validated by `composer check`. - - Please include Unit Tests to verify that a bug exists, and that this PR fixes it. - - Please include Unit Tests to show that a new Feature works as expected. - - Please don't "bundle" several changes into a single PR; submit a PR for each discrete change/fix. - - Remember to update documentation if necessary. - + - All new development happens on feature/fix branches referenced with the GitHub issue number, and are then merged to the develop branch; so the develop branch is always the most up-to-date, working code + - The master branch only contains tagged releases + - If you are going to be submitting a pull request, please fork from develop, and submit your pull request back as a fix/feature branch referencing the GitHub issue number + - Code style might be automatically fixed by `composer fix` + - All code changes must be validated by `composer check` - [Helpful article about forking](https://help.github.com/articles/fork-a-repo/ "Forking a GitHub repository") - [Helpful article about pull requests](https://help.github.com/articles/using-pull-requests/ "Pull Requests") - -## Unit Tests - -When writing Unit Tests, please - - Always try to write Unit Tests for both the happy and unhappy paths. - - Put all assertions in the Test itself, not in an abstract class that the Test extends (even if this means code duplication between tests). - - Include any necessary `setup()` and `tearDown()` in the Test itself. - - If you change any global settings (such as system locale, or Compatibility Mode for Excel Function tests), make sure that you reset to the default in the `tearDown()`. - - Use the `ExcelError` functions in assertions for Excel Error values in Excel Function implementations. -
Not only does it reduce the risk of typos; but at some point in the future, ExcelError values will be an object rather than a string, and we won't then need to update all the tests. - - Don't over-complicate test code by testing happy and unhappy paths in the same test. - -This makes it easier to see exactly what is being tested when reviewing the PR. I want to be able to see it in the PR, not have to hunt in other unchanged classes to see what the test is doing. - -## How to release - -1. Complete CHANGELOG.md and commit -2. Create an annotated tag - 1. `git tag -a 1.2.3` - 2. Tag subject must be the version number, eg: `1.2.3` - 3. Tag body must be a copy-paste of the changelog entries. -3. Push the tag with `git push --tags`, GitHub Actions will create a GitHub release automatically, and the release details will automatically be sent to packagist. -4. By default, Github removes markdown headings in the Release Notes. You can either edit to restore these, or, probably preferably, change the default comment character on your system - `git config core.commentChar ";"`. - -> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) However, there are 4 branches which have been updated to apply security patches, and those may be tagged if future security updates are needed. -- release1291 -- release210 -- release222 -- release390 diff --git a/LICENSE b/LICENSE index 04a90f083e..c7338e3c2e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,345 @@ -MIT License - -Copyright (c) 2019-2025 PhpSpreadsheet Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +GNU LESSER GENERAL PUBLIC LICENSE + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/README.md b/README.md index 84b4b7be15..e63e26e367 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,33 @@ # PhpSpreadsheet -[![Build Status](https://github.com/PHPOffice/PhpSpreadsheet/workflows/main/badge.svg)](https://github.com/PHPOffice/PhpSpreadsheet/actions) +Master: +[![Build Status](https://travis-ci.org/PHPOffice/PhpSpreadsheet.svg?branch=master)](https://travis-ci.org/PHPOffice/PhpSpreadsheet) [![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=master) -[![Total Downloads](https://img.shields.io/packagist/dt/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet) -[![Latest Stable Version](https://img.shields.io/github/v/release/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet) -[![License](https://img.shields.io/github/license/PHPOffice/PhpSpreadsheet)](https://packagist.org/packages/phpoffice/phpspreadsheet) +[![Total Downloads](https://poser.pugx.org/phpoffice/phpspreadsheet/downloads.png)](https://packagist.org/packages/phpoffice/phpspreadsheet) +[![Latest Stable Version](https://poser.pugx.org/phpoffice/phpspreadsheet/v/stable.png)](https://packagist.org/packages/phpoffice/phpspreadsheet) +[![License](https://poser.pugx.org/phpoffice/phpspreadsheet/license.png)](https://packagist.org/packages/phpoffice/phpspreadsheet) [![Join the chat at https://gitter.im/PHPOffice/PhpSpreadsheet](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PhpSpreadsheet) -PhpSpreadsheet is a library written in pure PHP and offers a set of classes that -allow you to read and write various spreadsheet file formats such as Excel and LibreOffice Calc. +Develop: +[![Build Status](https://travis-ci.org/PHPOffice/PhpSpreadsheet.png?branch=develop)](http://travis-ci.org/PHPOffice/PhpSpreadsheet) +[![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=develop) +[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/badges/coverage.png?b=develop)](https://scrutinizer-ci.com/g/PHPOffice/PhpSpreadsheet/?branch=develop) -## Installation - -See the [install instructions](https://phpspreadsheet.readthedocs.io/en/latest/#installation). +PhpSpreadsheet is a library written in pure PHP and providing a set of classes that allow you to read from and to write to different spreadsheet file formats, like Excel and LibreOffice Calc. ## Documentation -Read more about it, including install instructions, in the [official documentation](https://phpspreadsheet.readthedocs.io). Or check out the [API documentation](https://phpoffice.github.io/PhpSpreadsheet). - -Please ask your support questions on [StackOverflow](https://stackoverflow.com/questions/tagged/phpspreadsheet), or have a quick chat on [Gitter](https://gitter.im/PHPOffice/PhpSpreadsheet). - -## Patreon - -I am now running a [Patreon](https://www.patreon.com/MarkBaker) to support the work that I do on PhpSpreadsheet. - -Supporters will receive access to articles about working with PhpSpreadsheet, and how to use some of its more advanced features. - -Posts already available to Patreon supporters: - - The Dating Game - - A look at how MS Excel (and PhpSpreadsheet) handle date and time values. -- Looping the Loop - - Advice on Iterating through the rows and cells in a worksheet. +Read more about it, including install instructions, in the [official documentation](https://phpspreadsheet.readthedocs.io). Or check out the [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master). -And for Patrons at levels actively using PhpSpreadsheet: - - Behind the Mask - - A look at Number Format Masks. - -The Next Article (currently Work in Progress): - - Formula for Success - - How to debug formulae that don't produce the expected result. - - -My aim is to post at least one article each month, taking a detailed look at some feature of MS Excel and how to use that feature in PhpSpreadsheet, or on how to perform different activities in PhpSpreadsheet. - -Planned posts for the future include topics like: - - Tables - - Structured References - - AutoFiltering - - Array Formulae - - Conditional Formatting - - Data Validation - - Value Binders - - Images - - Charts - -After a period of six months exclusive to Patreon supporters, articles will be incorporated into the public documentation for the library. +Please ask your support questions on [StackOverflow](http://stackoverflow.com/questions/tagged/phpspreadsheet), or have a quick chat on [Gitter](https://gitter.im/PHPOffice/PhpSpreadsheet). ## PHPExcel vs PhpSpreadsheet ? PhpSpreadsheet is the next version of PHPExcel. It breaks compatibility to dramatically improve the code base quality (namespaces, PSR compliance, use of latest PHP language features, etc.). -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. +Because all efforts have shifted to PhpSpreadsheet, PHPExcel will no longer be maintained. All contributions for PHPExcel, patches and new features, should target PhpSpreadsheet develop branch. ## License -PhpSpreadsheet is licensed under [MIT](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/LICENSE). +PhpSpreadsheet is licensed under [LGPL (GNU LESSER GENERAL PUBLIC LICENSE)](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/LICENSE) diff --git a/bin/check-phpdoc-types.php b/bin/check-phpdoc-types.php deleted file mode 100755 index 1c620ea73e..0000000000 --- a/bin/check-phpdoc-types.php +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env php -generateLocales(); diff --git a/bin/migrate-from-phpexcel b/bin/migrate-from-phpexcel new file mode 100755 index 0000000000..51c60d495a --- /dev/null +++ b/bin/migrate-from-phpexcel @@ -0,0 +1,8 @@ +#!/usr/bin/env php +migrate(); diff --git a/bin/pre-commit b/bin/pre-commit index 348bb7174a..8d93f8abb6 100755 --- a/bin/pre-commit +++ b/bin/pre-commit @@ -14,7 +14,7 @@ if [ "$files" != "" ]; then done <<< "$files" # Run php-cs-fixer validation before commit - echo "$files" | xargs ./vendor/bin/php-cs-fixer fix --diff --config .php-cs-fixer.dist.php + echo "$files" | xargs ./vendor/bin/php-cs-fixer fix --diff --config .php_cs.dist if [ $? -ne 0 ]; then pass=false fi @@ -23,12 +23,6 @@ if [ "$files" != "" ]; then echo "$files" | xargs git add fi -# Check PHPDoc types -./bin/check-phpdoc-types.php -if [ $? -ne 0 ]; then - pass=false -fi - if $pass; then exit 0 else diff --git a/composer.json b/composer.json index bf03b9a795..ce228ad6fd 100644 --- a/composer.json +++ b/composer.json @@ -1,113 +1,68 @@ { "name": "phpoffice/phpspreadsheet", "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", - "keywords": [ - "PHP", - "OpenXML", - "Excel", - "xlsx", - "xls", - "ods", - "gnumeric", - "spreadsheet" - ], - "config": { - "platform": { - "php" : "8.1.99" - }, - "process-timeout": 600, - "sort-packages": true, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } - }, + "keywords": ["PHP", "OpenXML", "Excel", "xlsx", "xls", "ods", "gnumeric", "spreadsheet"], "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", "type": "library", - "license": "MIT", + "license": "LGPL-2.1-or-later", "authors": [ { "name": "Maarten Balliauw", - "homepage": "https://blog.maartenballiauw.be" + "homepage": "http://blog.maartenballiauw.be" }, { "name": "Mark Baker", - "homepage": "https://markbakeruk.net" + "homepage": "http://markbakeruk.net" }, { "name": "Franck Lefevre", - "homepage": "https://rootslabs.net" + "homepage": "http://rootslabs.net" }, { "name": "Erik Tilt" - }, - { - "name": "Adrien Crivelli" } ], "scripts": { "check": [ - "php bin/check-phpdoc-types.php", - "phpcs samples/ src/ tests/ --report=checkstyle", - "phpcs samples/ src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 8.0- --exclude=PHPCompatibility.Variables.ForbiddenThisUseContexts -n", "php-cs-fixer fix --ansi --dry-run --diff", - "phpstan analyse --ansi --memory-limit=2048M", + "phpcs --report-width=200 samples/ src/ tests/ --ignore=samples/Header.php --standard=PSR2 -n", "phpunit --color=always" ], - "style": [ - "phpcs samples/ src/ tests/ --report=checkstyle", - "php-cs-fixer fix --ansi --dry-run --diff" - ], "fix": [ - "phpcbf samples/ src/ tests/ --report=checkstyle", - "php-cs-fixer fix" - ], - "versions": [ - "phpcs samples/ src/ tests/ --standard=PHPCompatibility --runtime-set testVersion 8.0- --exclude=PHPCompatibility.Variables.ForbiddenThisUseContexts -n" + "php-cs-fixer fix --ansi" ] }, "require": { - "php": "^8.1", + "php": "^5.6|^7.0", "ext-ctype": "*", "ext-dom": "*", - "ext-fileinfo": "*", "ext-gd": "*", "ext-iconv": "*", "ext-libxml": "*", "ext-mbstring": "*", - "ext-simplexml": "*", + "ext-SimpleXML": "*", "ext-xml": "*", "ext-xmlreader": "*", "ext-xmlwriter": "*", "ext-zip": "*", "ext-zlib": "*", - "composer/pcre": "^1||^2||^3", - "maennchen/zipstream-php": "^2.1 || ^3.0", - "markbaker/complex": "^3.0", - "markbaker/matrix": "^3.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0", - "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" + "psr/simple-cache": "^1.0", + "markbaker/complex": "^1.4.1" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-main", - "dompdf/dompdf": "^2.0 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", - "mpdf/mpdf": "^8.1.1", - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.1 || ^2.0", - "phpstan/phpstan-phpunit": "^1.0 || ^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0 || ^2.0", - "phpunit/phpunit": "^10.5", - "squizlabs/php_codesniffer": "^3.7", - "tecnickcom/tcpdf": "^6.5" + "tecnickcom/tcpdf": "^6.2", + "phpunit/phpunit": "^5.7", + "dompdf/dompdf": "^0.8.0", + "mpdf/mpdf": "^7.0.0", + "jpgraph/jpgraph": "^4.0", + "friendsofphp/php-cs-fixer": "@stable", + "squizlabs/php_codesniffer": "^3.3" }, "suggest": { - "ext-intl": "PHP Internationalization Functions", "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "dompdf/dompdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer", - "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers" + "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers" }, "autoload": { "psr-4": { @@ -116,8 +71,7 @@ }, "autoload-dev": { "psr-4": { - "PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests", - "PhpOffice\\PhpSpreadsheetInfra\\": "infra" + "PhpOffice\\PhpSpreadsheetTests\\": "tests/PhpSpreadsheetTests" } } } diff --git a/composer.lock b/composer.lock index 6044de2dac..fe9fbc6553 100644 --- a/composer.lock +++ b/composer.lock @@ -4,48 +4,84 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eebf758015c7124f27782196c50a3253", + "content-hash": "66067b3ab7afd673a28cf0b31eb9ae20", "packages": [ { - "name": "composer/pcre", - "version": "3.3.2", + "name": "markbaker/complex", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "615f5443473cf37729666e2354fd8dfa2cb48e91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/615f5443473cf37729666e2354fd8dfa2cb48e91", + "reference": "615f5443473cf37729666e2354fd8dfa2cb48e91", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<1.11.10" + "php": "^5.6.0|^7.0.0" }, "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "2.*", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.35|^5.4.0", + "sebastian/phpcpd": "2.*", + "squizlabs/php_codesniffer": "^3.1.1", + "wimg/php-compatibility": "^8.0" }, "type": "library", - "extra": { - "phpstan": { - "includes": [ - "extension.neon" - ] - }, - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Pcre\\": "src" - } + "Complex\\": "classes/src/" + }, + "files": [ + "classes/src/functions/abs.php", + "classes/src/functions/acos.php", + "classes/src/functions/acosh.php", + "classes/src/functions/acot.php", + "classes/src/functions/acoth.php", + "classes/src/functions/acsc.php", + "classes/src/functions/acsch.php", + "classes/src/functions/argument.php", + "classes/src/functions/asec.php", + "classes/src/functions/asech.php", + "classes/src/functions/asin.php", + "classes/src/functions/asinh.php", + "classes/src/functions/atan.php", + "classes/src/functions/atanh.php", + "classes/src/functions/conjugate.php", + "classes/src/functions/cos.php", + "classes/src/functions/cosh.php", + "classes/src/functions/cot.php", + "classes/src/functions/coth.php", + "classes/src/functions/csc.php", + "classes/src/functions/csch.php", + "classes/src/functions/exp.php", + "classes/src/functions/inverse.php", + "classes/src/functions/ln.php", + "classes/src/functions/log2.php", + "classes/src/functions/log10.php", + "classes/src/functions/negative.php", + "classes/src/functions/pow.php", + "classes/src/functions/rho.php", + "classes/src/functions/sec.php", + "classes/src/functions/sech.php", + "classes/src/functions/sin.php", + "classes/src/functions/sinh.php", + "classes/src/functions/sqrt.php", + "classes/src/functions/tan.php", + "classes/src/functions/tanh.php", + "classes/src/functions/theta.php", + "classes/src/operations/add.php", + "classes/src/operations/subtract.php", + "classes/src/operations/multiply.php", + "classes/src/operations/divideby.php", + "classes/src/operations/divideinto.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -53,74 +89,44 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" } ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } + "complex", + "mathematics" ], - "time": "2024-11-12T16:29:46+00:00" + "time": "2018-07-24T19:47:28+00:00" }, { - "name": "maennchen/zipstream-php", - "version": "3.1.1", + "name": "psr/simple-cache", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "6187e9cc4493da94b9b63eb2315821552015fca9" + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9", - "reference": "6187e9cc4493da94b9b63eb2315821552015fca9", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/753fa598e8f3b9966c886fe13f370baa45ef0e24", + "reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24", "shasum": "" }, "require": { - "ext-mbstring": "*", - "ext-zlib": "*", - "php-64bit": "^8.1" - }, - "require-dev": { - "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.16", - "guzzlehttp/guzzle": "^7.5", - "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^10.0", - "vimeo/psalm": "^5.0" - }, - "suggest": { - "guzzlehttp/psr7": "^2.4", - "psr/http-message": "^2.0" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "ZipStream\\": "src/" + "Psr\\SimpleCache\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -129,66 +135,52 @@ ], "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" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "description": "Common interfaces for simple caching", "keywords": [ - "stream", - "zip" - ], - "support": { - "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/maennchen", - "type": "github" - } + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" ], - "time": "2024-10-10T12:33:01+00:00" - }, + "time": "2017-01-02T13:31:39+00:00" + } + ], + "packages-dev": [ { - "name": "markbaker/complex", - "version": "3.0.2", + "name": "composer/semver", + "version": "1.4.2", "source": { "type": "git", - "url": "https://github.com/MarkBaker/PHPComplex.git", - "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9" + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9", - "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^5.3.2 || ^7.0" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", - "phpcompatibility/php-compatibility": "^9.3", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "squizlabs/php_codesniffer": "^3.7" + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, "autoload": { "psr-4": { - "Complex\\": "classes/src/" + "Composer\\Semver\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -197,53 +189,61 @@ ], "authors": [ { - "name": "Mark Baker", - "email": "mark@lange.demon.co.uk" + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" } ], - "description": "PHP Class for working with complex numbers", - "homepage": "https://github.com/MarkBaker/PHPComplex", + "description": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ - "complex", - "mathematics" + "semantic", + "semver", + "validation", + "versioning" ], - "support": { - "issues": "https://github.com/MarkBaker/PHPComplex/issues", - "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2" - }, - "time": "2022-12-06T16:21:08+00:00" + "time": "2016-08-30T16:08:34+00:00" }, { - "name": "markbaker/matrix", - "version": "3.0.1", + "name": "doctrine/annotations", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/MarkBaker/PHPMatrix.git", - "reference": "728434227fe21be27ff6d86621a1b13107a2562c" + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c", - "reference": "728434227fe21be27ff6d86621a1b13107a2562c", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "doctrine/lexer": "1.*", + "php": "^7.1" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "dev-master", - "phpcompatibility/php-compatibility": "^9.3", - "phpdocumentor/phpdocumentor": "2.*", - "phploc/phploc": "^4.0", - "phpmd/phpmd": "2.*", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", - "sebastian/phpcpd": "^4.0", - "squizlabs/php_codesniffer": "^3.7" + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, "autoload": { "psr-4": { - "Matrix\\": "classes/src/" + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", @@ -252,40 +252,58 @@ ], "authors": [ { - "name": "Mark Baker", - "email": "mark@demon-angel.eu" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "PHP Class for working with matrices", - "homepage": "https://github.com/MarkBaker/PHPMatrix", + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "mathematics", - "matrix", - "vector" + "annotations", + "docblock", + "parser" ], - "support": { - "issues": "https://github.com/MarkBaker/PHPMatrix/issues", - "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1" - }, - "time": "2022-12-02T22:17:43+00:00" + "time": "2017-12-06T07:11:42+00:00" }, { - "name": "psr/http-client", - "version": "1.0.3", + "name": "doctrine/instantiator", + "version": "1.0.5", "source": { "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.0" + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { @@ -295,7 +313,7 @@ }, "autoload": { "psr-4": { - "Psr\\Http\\Client\\": "src/" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -304,40 +322,35 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", "keywords": [ - "http", - "http-client", - "psr", - "psr-18" + "constructor", + "instantiate" ], - "support": { - "source": "https://github.com/php-fig/http-client" - }, - "time": "2023-09-23T14:17:50+00:00" + "time": "2015-06-14T21:17:01+00:00" }, { - "name": "psr/http-factory", - "version": "1.1.0", + "name": "doctrine/lexer", + "version": "v1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", - "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { - "php": ">=7.1", - "psr/http-message": "^1.0 || ^2.0" + "php": ">=5.3.2" }, "type": "library", "extra": { @@ -346,8 +359,8 @@ } }, "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -356,106 +369,159 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", "keywords": [ - "factory", - "http", - "message", - "psr", - "psr-17", - "psr-7", - "request", - "response" + "lexer", + "parser" ], - "support": { - "source": "https://github.com/php-fig/http-factory" - }, - "time": "2024-04-15T12:06:14+00:00" + "time": "2014-09-09T13:34:57+00:00" }, { - "name": "psr/http-message", - "version": "2.0", + "name": "dompdf/dompdf", + "version": "v0.8.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + "url": "https://github.com/dompdf/dompdf.git", + "reference": "0f418c6b58fdeafc2a0e80eb1fa5e644e185089c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/0f418c6b58fdeafc2a0e80eb1fa5e644e185089c", + "reference": "0f418c6b58fdeafc2a0e80eb1fa5e644e185089c", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "ext-dom": "*", + "ext-gd": "*", + "ext-mbstring": "*", + "phenx/php-font-lib": "0.5.*", + "phenx/php-svg-lib": "0.2.*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*", + "squizlabs/php_codesniffer": "2.*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-develop": "0.7-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-2.1" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + }, + { + "name": "Brian Sweeney", + "email": "eclecticgeek@gmail.com" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "time": "2017-02-16T02:40:40+00:00" }, { - "name": "psr/simple-cache", - "version": "3.0.0", + "name": "friendsofphp/php-cs-fixer", + "version": "v2.10.0", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "513a3765b56dd029175f9f32995566657ee89dda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/513a3765b56dd029175f9f32995566657ee89dda", + "reference": "513a3765b56dd029175f9f32995566657ee89dda", "shasum": "" }, "require": { - "php": ">=8.0.0" + "composer/semver": "^1.4", + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "gecko-packages/gecko-php-unit": "^2.0 || ^3.0", + "php": "^5.6 || >=7.0 <7.3", + "php-cs-fixer/diff": "^1.2", + "symfony/console": "^3.2 || ^4.0", + "symfony/event-dispatcher": "^3.0 || ^4.0", + "symfony/filesystem": "^3.0 || ^4.0", + "symfony/finder": "^3.0 || ^4.0", + "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^3.0 || ^4.0", + "symfony/stopwatch": "^3.0 || ^4.0" }, - "type": "library", + "conflict": { + "hhvm": "*" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.1 || ^2.0@dev", + "justinrainbow/json-schema": "^5.0", + "keradus/cli-executor": "^1.0", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.0", + "php-cs-fixer/accessible-object": "^1.0", + "phpunit/phpunit": "^5.7.23 || ^6.4.3", + "phpunitgoodpractices/traits": "^1.0", + "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "2.10-dev" } }, "autoload": { "psr-4": { - "Psr\\SimpleCache\\": "src/" - } + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/Assert/AssertTokensTrait.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php", + "tests/TestCase.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -463,120 +529,88 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], - "support": { - "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" - }, - "time": "2021-10-29T13:26:27+00:00" - } - ], - "packages-dev": [ + "description": "A tool to automatically fix PHP code style", + "time": "2018-01-10T17:16:15+00:00" + }, { - "name": "clue/ndjson-react", - "version": "v1.3.0", + "name": "gecko-packages/gecko-php-unit", + "version": "v3.0", "source": { "type": "git", - "url": "https://github.com/clue/reactphp-ndjson.git", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" + "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git", + "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", - "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", + "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/6a866551dffc2154c1b091bae3a7877d39c25ca3", + "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3", "shasum": "" }, "require": { - "php": ">=5.3", - "react/stream": "^1.2" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", - "react/event-loop": "^1.2" + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-dom": "When testing with xml.", + "ext-libxml": "When testing with xml.", + "phpunit/phpunit": "This is an extension for it so make sure you have it some way." }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, "autoload": { "psr-4": { - "Clue\\React\\NDJson\\": "src/" + "GeckoPackages\\PHPUnit\\": "src/PHPUnit" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Christian Lück", - "email": "christian@clue.engineering" - } - ], - "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", - "homepage": "https://github.com/clue/reactphp-ndjson", + "description": "Additional PHPUnit asserts and constraints.", + "homepage": "https://github.com/GeckoPackages", "keywords": [ - "NDJSON", - "json", - "jsonlines", - "newline", - "reactphp", - "streaming" - ], - "support": { - "issues": "https://github.com/clue/reactphp-ndjson/issues", - "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" - }, - "funding": [ - { - "url": "https://clue.engineering/support", - "type": "custom" - }, - { - "url": "https://github.com/clue", - "type": "github" - } + "extension", + "filesystem", + "phpunit" ], - "time": "2022-12-23T10:58:28+00:00" + "time": "2017-08-23T07:46:41+00:00" }, { - "name": "composer/semver", - "version": "3.4.3", + "name": "ircmaxell/password-compat", + "version": "v1.0.4", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", "shasum": "" }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, "require-dev": { - "phpstan/phpstan": "^1.11", - "symfony/phpunit-bridge": "^3 || ^7" + "phpunit/phpunit": "4.*" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } + "files": [ + "lib/password.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -584,540 +618,195 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } + "hashing", + "password" ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2014-11-20T16:49:30+00:00" }, { - "name": "composer/xdebug-handler", - "version": "3.0.5", + "name": "jpgraph/jpgraph", + "version": "4.0.2", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + "url": "https://github.com/ztec/JpGraph.git", + "reference": "e82db7da6a546d3926c24c9a346226da7aa49094" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", - "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "url": "https://api.github.com/repos/ztec/JpGraph/zipball/e82db7da6a546d3926c24c9a346226da7aa49094", + "reference": "e82db7da6a546d3926c24c9a346226da7aa49094", "shasum": "" }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" - }, "type": "library", "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2024-05-06T16:37:16+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "a97da0ee61b752ff3318785d50bea8a67ee515e6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/a97da0ee61b752ff3318785d50bea8a67ee515e6", - "reference": "a97da0ee61b752ff3318785d50bea8a67ee515e6", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.2", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "^2.2", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" - }, - "default-branch": true, - "type": "composer-plugin", - "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } + "classmap": [ + "lib/JpGraph.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "QPL 1.0" ], "authors": [ { - "name": "Franck Nijhof", - "email": "opensource@frenck.dev", - "homepage": "https://frenck.dev", - "role": "Open source developer" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + "name": "JpGraph team" } ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "description": "jpGraph, library to make graphs and charts", + "homepage": "http://jpgraph.net/", "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - } + "chart", + "data", + "graph", + "jpgraph", + "pie" ], - "time": "2025-01-19T21:20:38+00:00" + "time": "2017-02-23T09:44:15+00:00" }, { - "name": "dompdf/dompdf", - "version": "v3.1.0", + "name": "mpdf/mpdf", + "version": "v7.0.0", "source": { "type": "git", - "url": "https://github.com/dompdf/dompdf.git", - "reference": "a51bd7a063a65499446919286fb18b518177155a" + "url": "https://github.com/mpdf/mpdf.git", + "reference": "375a79a575fde762a7c390766837e78e8dfe97bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a", - "reference": "a51bd7a063a65499446919286fb18b518177155a", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/375a79a575fde762a7c390766837e78e8dfe97bf", + "reference": "375a79a575fde762a7c390766837e78e8dfe97bf", "shasum": "" }, "require": { - "dompdf/php-font-lib": "^1.0.0", - "dompdf/php-svg-lib": "^1.0.0", - "ext-dom": "*", + "ext-gd": "*", "ext-mbstring": "*", - "masterminds/html5": "^2.0", - "php": "^7.1 || ^8.0" + "paragonie/random_compat": "^2.0", + "php": "^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0", + "psr/log": "^1.0", + "setasign/fpdi": "1.6.*" }, "require-dev": { - "ext-gd": "*", - "ext-json": "*", - "ext-zip": "*", - "mockery/mockery": "^1.3", - "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + "mockery/mockery": "^0.9.5", + "phpunit/phpunit": "^5.0", + "squizlabs/php_codesniffer": "^2.7.0", + "tracy/tracy": "^2.4" }, "suggest": { - "ext-gd": "Needed to process images", - "ext-gmagick": "Improves image processing performance", - "ext-imagick": "Improves image processing performance", - "ext-zlib": "Needed for pdf stream compression" - }, - "type": "library", - "autoload": { - "psr-4": { - "Dompdf\\": "src/" - }, - "classmap": [ - "lib/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1" - ], - "authors": [ - { - "name": "The Dompdf Community", - "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" - } - ], - "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", - "homepage": "https://github.com/dompdf/dompdf", - "support": { - "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.0" - }, - "time": "2025-01-15T14:09:04+00:00" - }, - { - "name": "dompdf/php-font-lib", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", - "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + "ext-bcmath": "Needed for generation of some types of barcodes", + "ext-xml": "Needed mainly for SVG manipulation", + "ext-zlib": "Needed for compression of embedded resources, such as fonts" }, "type": "library", - "autoload": { - "psr-4": { - "FontLib\\": "src/FontLib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-2.1-or-later" - ], - "authors": [ - { - "name": "The FontLib Community", - "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + "extra": { + "branch-alias": { + "dev-development": "7.0-dev" } - ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/dompdf/php-font-lib", - "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" }, - "time": "2024-12-02T14:37:59+00:00" - }, - { - "name": "dompdf/php-svg-lib", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" - }, - "type": "library", "autoload": { "psr-4": { - "Svg\\": "src/Svg" + "Mpdf\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "GPL-2.0" ], "authors": [ { - "name": "The SvgLib Community", - "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" - } - ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/dompdf/php-svg-lib", - "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" - }, - "time": "2024-04-29T13:26:35+00:00" - }, - { - "name": "evenement/evenement", - "version": "v3.0.2", - "source": { - "type": "git", - "url": "https://github.com/igorw/evenement.git", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", - "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", - "shasum": "" - }, - "require": { - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^9 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Evenement\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "name": "Matěj Humpál", + "role": "Developer, maintainer" + }, { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" + "name": "Ian Back", + "role": "Developer (retired)" } ], - "description": "Événement is a very simple event dispatching library for PHP", + "description": "A PHP class to generate PDF files from HTML with Unicode/UTF-8 and CJK support", + "homepage": "https://mpdf.github.io", "keywords": [ - "event-dispatcher", - "event-emitter" + "pdf", + "php", + "utf-8" ], - "support": { - "issues": "https://github.com/igorw/evenement/issues", - "source": "https://github.com/igorw/evenement/tree/v3.0.2" - }, - "time": "2023-08-08T05:53:35+00:00" + "time": "2017-10-19T16:38:45+00:00" }, { - "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "name": "myclabs/deep-copy", + "version": "1.6.0", "source": { "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe", + "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=5.4.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" }, "type": "library", "autoload": { "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } + "clone", + "copy", + "duplicate", + "object", + "object graph" ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2017-01-26T22:05:40+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.75.0", + "name": "paragonie/random_compat", + "version": "v2.0.11", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c" + "url": "https://github.com/paragonie/random_compat.git", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c", - "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", "shasum": "" }, "require": { - "clue/ndjson-react": "^1.0", - "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.3", - "ext-filter": "*", - "ext-hash": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", - "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.5", - "react/event-loop": "^1.0", - "react/promise": "^2.0 || ^3.0", - "react/socket": "^1.0", - "react/stream": "^1.0", - "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", - "symfony/console": "^5.4 || ^6.4 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", - "symfony/finder": "^5.4 || ^6.4 || ^7.0", - "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", - "symfony/polyfill-mbstring": "^1.31", - "symfony/polyfill-php80": "^1.31", - "symfony/polyfill-php81": "^1.31", - "symfony/process": "^5.4 || ^6.4 || ^7.2", - "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" + "php": ">=5.2.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.6", - "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.2", - "keradus/cli-executor": "^2.1", - "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.7", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12", - "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3", - "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3" + "phpunit/phpunit": "4.*|5.*" }, "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", + "type": "library", "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - }, - "exclude-from-classmap": [ - "src/Fixer/Internal/*" + "files": [ + "lib/random.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1126,1508 +815,172 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" } ], - "time": "2025-03-31T18:40:42+00:00" - }, - { - "name": "masterminds/html5", - "version": "2.9.0", - "source": { - "type": "git", - "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Masterminds\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matt Butcher", - "email": "technosophos@gmail.com" - }, - { - "name": "Matt Farina", - "email": "matt@mattfarina.com" - }, - { - "name": "Asmir Mustafic", - "email": "goetas@gmail.com" - } - ], - "description": "An HTML5 parser and serializer.", - "homepage": "http://masterminds.github.io/html5-php", - "keywords": [ - "HTML5", - "dom", - "html", - "parser", - "querypath", - "serializer", - "xml" - ], - "support": { - "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" - }, - "time": "2024-03-31T07:05:07+00:00" - }, - { - "name": "mitoteam/jpgraph", - "version": "10.4.4", - "source": { - "type": "git", - "url": "https://github.com/mitoteam/jpgraph.git", - "reference": "9ad8e2fcc30f765c788a28543e9705fb541d499f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mitoteam/jpgraph/zipball/9ad8e2fcc30f765c788a28543e9705fb541d499f", - "reference": "9ad8e2fcc30f765c788a28543e9705fb541d499f", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "replace": { - "jpgraph/jpgraph": "4.0.2", - "rulin132/jpgraph": "4.3.5" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/MtJpGraph.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "QPL-1.0" - ], - "authors": [ - { - "name": "JpGraph team", - "homepage": "https://jpgraph.net", - "role": "Original Library Developers" - }, - { - "name": "MiTo Team", - "email": "info@mito-team.com", - "homepage": "https://www.mito-team.com", - "role": "Composer package maintenance, PHP-compatibility patches" - } - ], - "description": "JpGraph library composer package with PHP 8.4 support", - "homepage": "https://github.com/mitoteam/jpgraph", - "keywords": [ - "jpgraph" - ], - "support": { - "issues": "https://github.com/mitoteam/jpgraph/issues", - "source": "https://github.com/mitoteam/jpgraph/tree/10.4.4" - }, - "time": "2025-01-01T05:39:20+00:00" - }, - { - "name": "mpdf/mpdf", - "version": "v8.2.5", - "source": { - "type": "git", - "url": "https://github.com/mpdf/mpdf.git", - "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/e175b05e3e00977b85feb96a8cccb174ac63621f", - "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f", - "shasum": "" - }, - "require": { - "ext-gd": "*", - "ext-mbstring": "*", - "mpdf/psr-http-message-shim": "^1.0 || ^2.0", - "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", - "myclabs/deep-copy": "^1.7", - "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", - "psr/http-message": "^1.0 || ^2.0", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "setasign/fpdi": "^2.1" - }, - "require-dev": { - "mockery/mockery": "^1.3.0", - "mpdf/qrcode": "^1.1.0", - "squizlabs/php_codesniffer": "^3.5.0", - "tracy/tracy": "~2.5", - "yoast/phpunit-polyfills": "^1.0" - }, - "suggest": { - "ext-bcmath": "Needed for generation of some types of barcodes", - "ext-xml": "Needed mainly for SVG manipulation", - "ext-zlib": "Needed for compression of embedded resources, such as fonts" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Mpdf\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-2.0-only" - ], - "authors": [ - { - "name": "Matěj Humpál", - "role": "Developer, maintainer" - }, - { - "name": "Ian Back", - "role": "Developer (retired)" - } - ], - "description": "PHP library generating PDF files from UTF-8 encoded HTML", - "homepage": "https://mpdf.github.io", - "keywords": [ - "pdf", - "php", - "utf-8" - ], - "support": { - "docs": "https://mpdf.github.io", - "issues": "https://github.com/mpdf/mpdf/issues", - "source": "https://github.com/mpdf/mpdf" - }, - "funding": [ - { - "url": "https://www.paypal.me/mpdf", - "type": "custom" - } - ], - "time": "2024-11-18T15:30:42+00:00" - }, - { - "name": "mpdf/psr-http-message-shim", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-http-message-shim.git", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-http-message-shim/zipball/f25a0153d645e234f9db42e5433b16d9b113920f", - "reference": "f25a0153d645e234f9db42e5433b16d9b113920f", - "shasum": "" - }, - "require": { - "psr/http-message": "^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrHttpMessageShim\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - }, - { - "name": "Nigel Cunningham", - "email": "nigel.cunningham@technocrat.com.au" - } - ], - "description": "Shim to allow support of different psr/message versions.", - "support": { - "issues": "https://github.com/mpdf/psr-http-message-shim/issues", - "source": "https://github.com/mpdf/psr-http-message-shim/tree/v2.0.1" - }, - "time": "2023-10-02T14:34:03+00:00" - }, - { - "name": "mpdf/psr-log-aware-trait", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/mpdf/psr-log-aware-trait.git", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mpdf/psr-log-aware-trait/zipball/a633da6065e946cc491e1c962850344bb0bf3e78", - "reference": "a633da6065e946cc491e1c962850344bb0bf3e78", - "shasum": "" - }, - "require": { - "psr/log": "^3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mpdf\\PsrLogAwareTrait\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mark Dorison", - "email": "mark@chromatichq.com" - }, - { - "name": "Kristofer Widholm", - "email": "kristofer@chromatichq.com" - } - ], - "description": "Trait to allow support of different psr/log versions.", - "support": { - "issues": "https://github.com/mpdf/psr-log-aware-trait/issues", - "source": "https://github.com/mpdf/psr-log-aware-trait/tree/v3.0.0" - }, - "time": "2023-05-03T06:19:36+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.12.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2024-11-08T17:47:46+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.4.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" - }, - "time": "2024-12-30T11:07:19+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" - } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, - "time": "2019-12-27T09:44:58+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "2.1.17", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", - "shasum": "" - }, - "require": { - "php": "^7.4|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "keywords": [ - "dev", - "static analysis" - ], - "support": { - "docs": "https://phpstan.org/user-guide/getting-started", - "forum": "https://github.com/phpstan/phpstan/discussions", - "issues": "https://github.com/phpstan/phpstan/issues", - "security": "https://github.com/phpstan/phpstan/security/policy", - "source": "https://github.com/phpstan/phpstan-src" - }, - "funding": [ - { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", - "type": "github" - } - ], - "time": "2025-05-21T20:55:28+00:00" - }, - { - "name": "phpstan/phpstan-deprecation-rules", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.15" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", - "support": { - "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3" - }, - "time": "2025-05-14T10:56:57+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "d09e152f403c843998d7a52b5d87040c937525dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d09e152f403c843998d7a52b5d87040c937525dd", - "reference": "d09e152f403c843998d7a52b5d87040c937525dd", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.0.4" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-strict-rules": "^2.0", - "phpunit/phpunit": "^9.6" - }, - "type": "phpstan-extension", - "extra": { - "phpstan": { - "includes": [ - "extension.neon", - "rules.neon" - ] - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "support": { - "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.4" - }, - "time": "2025-01-22T13:07:38+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "10.1.16", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", - "reference": "7e308268858ed6baedc8704a304727d20bc07c77", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-text-template": "^3.0.1", - "sebastian/code-unit-reverse-lookup": "^3.0.0", - "sebastian/complexity": "^3.2.0", - "sebastian/environment": "^6.1.0", - "sebastian/lines-of-code": "^2.0.2", - "sebastian/version": "^4.0.1", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^10.1" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-08-22T04:31:57+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "4.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T06:24:48+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "4.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:56:09+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-31T14:07:24+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "6.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "6.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:57:52+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "10.5.45", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bd68a781d8e30348bc297449f5234b3458267ae8", - "reference": "bd68a781d8e30348bc297449f5234b3458267ae8", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.16", - "phpunit/php-file-iterator": "^4.1.0", - "phpunit/php-invoker": "^4.0.0", - "phpunit/php-text-template": "^3.0.1", - "phpunit/php-timer": "^6.0.0", - "sebastian/cli-parser": "^2.0.1", - "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.3", - "sebastian/diff": "^5.1.1", - "sebastian/environment": "^6.1.0", - "sebastian/exporter": "^5.1.2", - "sebastian/global-state": "^6.0.2", - "sebastian/object-enumerator": "^5.0.0", - "sebastian/recursion-context": "^5.0.0", - "sebastian/type": "^4.0.0", - "sebastian/version": "^4.0.1" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "10.5-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.45" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2025-02-06T16:08:12+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "csprng", + "pseudorandom", + "random" ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2017-09-27T21:40:39+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "phenx/php-font-lib", + "version": "0.5", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/PhenX/php-font-lib.git", + "reference": "19ad2bebc35be028fcc0221025fcbf3d436a3962" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/19ad2bebc35be028fcc0221025fcbf3d436a3962", + "reference": "19ad2bebc35be028fcc0221025fcbf3d436a3962", "shasum": "" }, - "require": { - "php": ">=7.2.0" + "require-dev": { + "phpunit/phpunit": "^4.8" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "FontLib\\": "src/FontLib" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" } ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", + "time": "2017-02-11T10:58:43+00:00" }, { - "name": "psr/log", - "version": "3.0.2", + "name": "phenx/php-svg-lib", + "version": "v0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + "url": "https://github.com/PhenX/php-svg-lib.git", + "reference": "de291bec8449b89acfe85691b5c71434797959dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/de291bec8449b89acfe85691b5c71434797959dc", + "reference": "de291bec8449b89acfe85691b5c71434797959dc", "shasum": "" }, "require": { - "php": ">=8.0.0" + "sabberworm/php-css-parser": "6.0.*" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "autoload": { - "psr-4": { - "Psr\\Log\\": "src" + "psr-0": { + "Svg\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "LGPL-3.0" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", + "time": "2016-12-13T20:25:45+00:00" }, { - "name": "react/cache", + "name": "php-cs-fixer/diff", "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/reactphp/cache.git", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + "url": "https://github.com/PHP-CS-Fixer/diff.git", + "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", - "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/f0ef6133d674137e902fdf8a6f2e8e97e14a087b", + "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b", "shasum": "" }, "require": { - "php": ">=5.3.0", - "react/promise": "^3.0 || ^2.0 || ^1.1" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^4.8.35 || ^5.4.3", + "symfony/process": "^3.3" }, "type": "library", "autoload": { - "psr-4": { - "React\\Cache\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" }, { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" + "name": "SpacePossum" } ], - "description": "Async, Promise-based cache interface for ReactPHP", + "description": "sebastian/diff v2 backport support for PHP5.6", + "homepage": "https://github.com/PHP-CS-Fixer", "keywords": [ - "cache", - "caching", - "promise", - "reactphp" + "diff" ], - "support": { - "issues": "https://github.com/reactphp/cache/issues", - "source": "https://github.com/reactphp/cache/tree/v1.2.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } - ], - "time": "2022-11-30T15:59:55+00:00" + "time": "2017-10-19T09:58:18+00:00" }, { - "name": "react/child-process", - "version": "v0.6.6", + "name": "phpdocumentor/reflection-common", + "version": "1.0", "source": { "type": "git", - "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", "shasum": "" }, "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/event-loop": "^1.2", - "react/stream": "^1.4" + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/socket": "^1.16", - "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + "phpunit/phpunit": "^4.6" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "React\\ChildProcess\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -2636,73 +989,51 @@ ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" } ], - "description": "Event-driven library for executing child processes with ReactPHP.", + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", "keywords": [ - "event-driven", - "process", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2015-12-27T11:43:31+00:00" }, { - "name": "react/dns", - "version": "v1.13.0", + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", "shasum": "" }, "require": { - "php": ">=5.3.0", - "react/cache": "^1.0 || ^0.6 || ^0.5", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.7 || ^1.2.1" + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3 || ^2", - "react/promise-timer": "^1.11" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" }, "type": "library", "autoload": { "psr-4": { - "React\\Dns\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -2711,72 +1042,46 @@ ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "Async DNS resolver for ReactPHP", - "keywords": [ - "async", - "dns", - "dns-resolver", - "reactphp" - ], - "support": { - "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "time": "2024-06-13T14:18:03+00:00" + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30T07:12:33+00:00" }, { - "name": "react/event-loop", - "version": "v1.5.0", + "name": "phpdocumentor/type-resolver", + "version": "0.2.1", "source": { "type": "git", - "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" - }, - "suggest": { - "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "React\\EventLoop\\": "src/" + "phpDocumentor\\Reflection\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -2785,71 +1090,46 @@ ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" - } - ], - "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", - "keywords": [ - "asynchronous", - "event-loop" - ], - "support": { - "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2016-11-25T06:54:22+00:00" }, { - "name": "react/promise", - "version": "v3.2.0", + "name": "phpspec/prophecy", + "version": "v1.7.0", "source": { "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "url": "https://github.com/phpspec/prophecy.git", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { - "php": ">=7.1.0" + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", - "phpunit/phpunit": "^9.6 || ^7.5" + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "React\\Promise\\": "src/" + "psr-0": { + "Prophecy\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2858,290 +1138,252 @@ ], "authors": [ { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" }, { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" } ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", "keywords": [ - "promise", - "promises" - ], - "support": { - "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2017-03-02T20:05:34+00:00" }, { - "name": "react/socket", - "version": "v1.16.0", + "name": "phpunit/php-code-coverage", + "version": "4.0.7", "source": { "type": "git", - "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", "shasum": "" }, "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.0", - "react/dns": "^1.13", - "react/event-loop": "^1.2", - "react/promise": "^3.2 || ^2.6 || ^1.2.1", - "react/stream": "^1.4" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "^1.0 || ^2.0" }, "require-dev": { - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4.3 || ^3.3 || ^2", - "react/promise-stream": "^1.4", - "react/promise-timer": "^1.11" + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" + }, + "suggest": { + "ext-xdebug": "^2.5.1" }, "type": "library", - "autoload": { - "psr-4": { - "React\\Socket\\": "src/" + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "Connection", - "Socket", - "async", - "reactphp", - "stream" + "coverage", + "testing", + "xunit" ], - "support": { - "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "time": "2017-03-01T09:12:17+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] }, - "funding": [ + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "time": "2024-07-26T10:38:09+00:00" + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2016-10-03T07:40:28+00:00" }, { - "name": "react/stream", - "version": "v1.4.0", + "name": "phpunit/php-text-template", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/reactphp/stream.git", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", - "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { - "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "php": ">=5.3.8", - "react/event-loop": "^1.2" - }, - "require-dev": { - "clue/stream-filter": "~1.2", - "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + "php": ">=5.3.3" }, "type": "library", "autoload": { - "psr-4": { - "React\\Stream\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Christian Lück", - "email": "christian@clue.engineering", - "homepage": "https://clue.engineering/" - }, - { - "name": "Cees-Jan Kiewiet", - "email": "reactphp@ceesjankiewiet.nl", - "homepage": "https://wyrihaximus.net/" - }, - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com", - "homepage": "https://sorgalla.com/" - }, - { - "name": "Chris Boden", - "email": "cboden@gmail.com", - "homepage": "https://cboden.dev/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "event-driven", - "io", - "non-blocking", - "pipe", - "reactphp", - "readable", - "stream", - "writable" - ], - "support": { - "issues": "https://github.com/reactphp/stream/issues", - "source": "https://github.com/reactphp/stream/tree/v1.4.0" - }, - "funding": [ - { - "url": "https://opencollective.com/reactphp", - "type": "open_collective" - } + "template" ], - "time": "2024-06-11T12:45:25+00:00" + "time": "2015-06-21T13:50:34+00:00" }, { - "name": "sabberworm/php-css-parser", - "version": "v8.7.0", + "name": "phpunit/php-timer", + "version": "1.0.9", "source": { "type": "git", - "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/f414ff953002a9b18e3a116f5e462c56f21237cf", - "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "ext-iconv": "*", - "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.40" - }, - "suggest": { - "ext-mbstring": "for parsing UTF-8 CSS" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "9.0.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-4": { - "Sabberworm\\CSS\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Raphael Schweikert" - }, - { - "name": "Oliver Klee", - "email": "github@oliverklee.de" - }, - { - "name": "Jake Hotson", - "email": "jake.github@qzdesign.co.uk" + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Parser for CSS Files written in PHP", - "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "css", - "parser", - "stylesheet" + "timer" ], - "support": { - "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.7.0" - }, - "time": "2024-10-27T17:38:32+00:00" + "time": "2017-02-26T11:10:40+00:00" }, { - "name": "sebastian/cli-parser", - "version": "2.0.1", + "name": "phpunit/php-token-stream", + "version": "1.4.11", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { - "php": ">=8.1" + "ext-tokenizer": "*", + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -3156,49 +1398,71 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2017-02-27T10:12:30+00:00" }, { - "name": "sebastian/code-unit", - "version": "2.0.0", + "name": "phpunit/phpunit", + "version": "5.7.17", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68752b665d3875f9a38a357e3ecb35c79f8673bf", + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf", "shasum": "" }, "require": { - "php": ">=8.1" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.4", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "^1.2.4", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.1", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0.3|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "ext-pdo": "*" }, + "suggest": { + "ext-xdebug": "*", + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { @@ -3217,44 +1481,48 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2017-03-19T16:52:12+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "name": "phpunit/phpunit-mock-objects", + "version": "3.4.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { - "php": ">=8.1" + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^5.4" + }, + "suggest": { + "ext-soap": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { @@ -3269,183 +1537,130 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sb@sebastian-bergmann.de", + "role": "lead" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2016-12-08T20:27:08+00:00" }, { - "name": "sebastian/comparator", - "version": "5.0.3", + "name": "psr/log", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", - "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^10.5" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "log", + "psr", + "psr-3" ], - "time": "2024-10-18T14:56:07+00:00" + "time": "2016-10-10T12:19:37+00:00" }, { - "name": "sebastian/complexity", - "version": "3.2.0", + "name": "sabberworm/php-css-parser", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", + "reference": "9ea4b00c569b19f731d0c2e0e802055877ff40c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/9ea4b00c569b19f731d0c2e0e802055877ff40c2", + "reference": "9ea4b00c569b19f731d0c2e0e802055877ff40c2", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "php": ">=5.3.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.2-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "Sabberworm\\CSS": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Raphael Schweikert" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "description": "Parser for CSS Files written in PHP", + "homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2015-08-24T08:48:52+00:00" }, { - "name": "sebastian/diff", - "version": "5.1.1", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=8.1" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -3461,60 +1676,38 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" }, { - "name": "sebastian/environment", - "version": "6.1.0", + "name": "sebastian/comparator", + "version": "1.2.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-posix": "*" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -3527,57 +1720,56 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "comparator", + "compare", + "equality" ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2017-01-29T09:50:25+00:00" }, { - "name": "sebastian/exporter", - "version": "5.1.2", + "name": "sebastian/diff", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-master": "1.4-dev" } }, "autoload": { @@ -3591,72 +1783,45 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" }, { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "diff" ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2015-12-08T07:14:41+00:00" }, { - "name": "sebastian/global-state", - "version": "6.0.2", + "name": "sebastian/environment", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3674,49 +1839,41 @@ "email": "sebastian@phpunit.de" } ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "Xdebug", + "environment", + "hhvm" ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2016-11-26T07:53:53+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "2.0.2", + "name": "sebastian/exporter", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3729,53 +1886,62 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" - }, - "funding": [ + "email": "sebastian@phpunit.de" + }, { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "time": "2023-12-21T08:38:20+00:00" + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19T08:54:04+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "5.0.0", + "name": "sebastian/global-state", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -3793,44 +1959,38 @@ "email": "sebastian@phpunit.de" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2015-10-12T03:26:01+00:00" }, { - "name": "sebastian/object-reflector", - "version": "3.0.0", + "name": "sebastian/object-enumerator", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "~5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3848,44 +2008,34 @@ "email": "sebastian@phpunit.de" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:06:18+00:00" + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-02-18T15:18:39+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3898,57 +2048,44 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T07:05:40+00:00" + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19T07:33:16+00:00" }, { - "name": "sebastian/type", - "version": "4.0.0", + "name": "sebastian/resource-operations", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", "shasum": "" }, "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" + "php": ">=5.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -3963,45 +2100,34 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "email": "sebastian@phpunit.de" } ], - "time": "2023-02-03T07:10:45+00:00" + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28T20:34:47+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.6" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4022,54 +2148,36 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2016-10-03T07:35:21+00:00" }, { "name": "setasign/fpdi", - "version": "v2.6.3", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/Setasign/FPDI.git", - "reference": "67c31f5e50c93c20579ca9e23035d8c540b51941" + "reference": "a6ad58897a6d97cc2d2cd2adaeda343b25a368ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/67c31f5e50c93c20579ca9e23035d8c540b51941", - "reference": "67c31f5e50c93c20579ca9e23035d8c540b51941", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6ad58897a6d97cc2d2cd2adaeda343b25a368ea", + "reference": "a6ad58897a6d97cc2d2cd2adaeda343b25a368ea", "shasum": "" }, - "require": { - "ext-zlib": "*", - "php": "^7.1 || ^8.0" - }, - "conflict": { - "setasign/tfpdf": "<1.31" - }, - "require-dev": { - "phpunit/phpunit": "^7", - "setasign/fpdf": "~1.8.6", - "setasign/tfpdf": "~1.33", - "squizlabs/php_codesniffer": "^3.5", - "tecnickcom/tcpdf": "^6.2" - }, "suggest": { - "setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured." + "setasign/fpdf": "FPDI will extend this class but as it is also possible to use \"tecnickcom/tcpdf\" as an alternative there's no fixed dependency configured.", + "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.", + "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF." }, "type": "library", "autoload": { - "psr-4": { - "setasign\\Fpdi\\": "src/" - } + "classmap": [ + "filters/", + "fpdi.php", + "fpdf_tpl.php", + "fpdi_pdf_parser.php", + "pdf_context.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4080,11 +2188,6 @@ "name": "Jan Slabon", "email": "jan.slabon@setasign.com", "homepage": "https://www.setasign.com" - }, - { - "name": "Maximilian Kresse", - "email": "maximilian.kresse@setasign.com", - "homepage": "https://www.setasign.com" } ], "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.", @@ -4094,30 +2197,20 @@ "fpdi", "pdf" ], - "support": { - "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.6.3" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/setasign/fpdi", - "type": "tidelift" - } - ], - "time": "2025-02-05T13:22:35+00:00" + "time": "2017-05-11T14:25:49+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.13.0", + "version": "3.3.1", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "65ff2489553b83b4597e89c3b8b721487011d186" + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "628a481780561150481a9ec74709092b9759b3ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186", - "reference": "65ff2489553b83b4597e89c3b8b721487011d186", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/628a481780561150481a9ec74709092b9759b3ec", + "reference": "628a481780561150481a9ec74709092b9759b3ec", "shasum": "" }, "require": { @@ -4127,11 +2220,11 @@ "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ - "bin/phpcbf", - "bin/phpcs" + "bin/phpcs", + "bin/phpcbf" ], "type": "library", "extra": { @@ -4146,95 +2239,59 @@ "authors": [ { "name": "Greg Sherwood", - "role": "Former lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "Current lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + "role": "lead" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "homepage": "http://www.squizlabs.com/php-codesniffer", "keywords": [ "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } + "standards" ], - "time": "2025-05-11T03:36:00+00:00" + "time": "2018-07-26T23:47:18+00:00" }, { "name": "symfony/console", - "version": "v6.4.20", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2e4af9c952617cc3f9559ff706aee420a8464c36" + "reference": "fe0e69d7162cba0885791cf7eea5f0d7bc0f897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2e4af9c952617cc3f9559ff706aee420a8464c36", - "reference": "2e4af9c952617cc3f9559ff706aee420a8464c36", + "url": "https://api.github.com/repos/symfony/console/zipball/fe0e69d7162cba0885791cf7eea5f0d7bc0f897e", + "reference": "fe0e69d7162cba0885791cf7eea5f0d7bc0f897e", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" @@ -4257,137 +2314,47 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.4.20" - }, - "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": "2025-03-03T17:16:38+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.5-dev" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", + "description": "Symfony Console Component", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" - }, - "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": "2024-09-25T14:20:29+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.13", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", - "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74d33aac36208c4d6757807d9f598f0133a3a4eb", + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2.5|^3" + "php": "^7.1.3" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/service-contracts": "<2.5" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0|3.0" + "symfony/dependency-injection": "<3.4" }, "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" @@ -4410,126 +2377,33 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" - }, - "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": "2024-09-25T14:18:03+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { - "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.1", + "name": "symfony/filesystem", + "version": "v4.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + "url": "https://github.com/symfony/filesystem.git", + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", - "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/760e47a4ee64b4c48f4b30017011e09d4c0f05ed", + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/event-dispatcher": "^1" + "php": "^7.1.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.5-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" - }, - "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" + "dev-master": "4.0-dev" } - ], - "time": "2024-09-25T14:20:29+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v6.4.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", - "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" - }, - "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" }, - "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" @@ -4552,113 +2426,36 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides basic utilities for the filesystem", + "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.13" - }, - "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": "2024-10-25T15:07:50+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/finder", - "version": "v6.4.17", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7" + "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", - "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", + "url": "https://api.github.com/repos/symfony/finder/zipball/8b08180f2b7ccb41062366b9ad91fbc4f1af8601", + "reference": "8b08180f2b7ccb41062366b9ad91fbc4f1af8601", "shasum": "" }, "require": { - "php": ">=8.1" - }, - "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "php": "^7.1.3" }, "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.17" - }, - "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" + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } - ], - "time": "2024-12-29T13:51:37+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v6.4.16", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "368128ad168f20e22c32159b9f761e456cec0c78" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/368128ad168f20e22c32159b9f761e456cec0c78", - "reference": "368128ad168f20e22c32159b9f761e456cec0c78", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -4678,69 +2475,40 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an improved replacement for the array_replace PHP function", + "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.16" - }, - "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": "2024-11-20T10:57:02+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "name": "symfony/options-resolver", + "version": "v4.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "url": "https://github.com/symfony/options-resolver.git", + "reference": "30d9240b30696a69e893534c9fc4a5c72ab6689b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/30d9240b30696a69e893534c9fc4a5c72ab6689b", + "reference": "30d9240b30696a69e893534c9fc4a5c72ab6689b", "shasum": "" }, "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" + "php": "^7.1.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "4.0-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4748,75 +2516,56 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Symfony OptionsResolver Component", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" - }, - "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" - } + "config", + "configuration", + "options" ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=5.3.3" }, "suggest": { - "ext-intl": "For best performance" + "ext-mbstring": "For best performance" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "1.6-dev" } }, "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, "files": [ "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4832,69 +2581,47 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's grapheme_* functions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "grapheme", - "intl", + "mbstring", "polyfill", "portable", "shim" ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" - }, - "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": "2024-09-09T11:45:10+00:00" + "time": "2017-10-11T12:05:26+00:00" }, { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "name": "symfony/polyfill-php54", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/90e085822963fdcc9d1c5b73deb3d2e5783b16a0", + "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0", "shasum": "" }, "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" + "php": ">=5.3.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "1.3-dev" } }, "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php54\\": "" + }, "files": [ "bootstrap.php" ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "classmap": [ "Resources/stubs" ] @@ -4913,72 +2640,47 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", + "description": "Symfony polyfill backporting some PHP 5.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "intl", - "normalizer", "polyfill", "portable", "shim" ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" - }, - "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": "2024-09-09T11:45:10+00:00" + "time": "2016-11-14T01:06:16+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "name": "symfony/polyfill-php55", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "03e3f0350bca2220e3623a0e340eef194405fc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/03e3f0350bca2220e3623a0e340eef194405fc67", + "reference": "03e3f0350bca2220e3623a0e340eef194405fc67", "shasum": "" }, "require": { - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "1.3-dev" } }, "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + }, "files": [ "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4994,65 +2696,47 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", "shim" ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" - }, - "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": "2024-09-09T11:45:10+00:00" + "time": "2016-11-14T01:06:16+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "name": "symfony/polyfill-php70", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", + "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", "shasum": "" }, "require": { - "php": ">=7.2" + "paragonie/random_compat": "~1.0|~2.0", + "php": ">=5.3.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "1.6-dev" } }, "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, "files": [ "bootstrap.php" ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, "classmap": [ "Resources/stubs" ] @@ -5062,10 +2746,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -5075,7 +2755,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -5083,58 +2763,37 @@ "portable", "shim" ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" - }, - "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": "2024-09-09T11:45:10+00:00" + "time": "2017-10-11T12:05:26+00:00" }, { - "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "name": "symfony/polyfill-php72", + "version": "v1.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/6de4f4884b97abbbed9f0a84a95ff2ff77254254", + "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=5.3.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" + "branch-alias": { + "dev-master": "1.6-dev" } }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php72\\": "" }, - "classmap": [ - "Resources/stubs" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5151,7 +2810,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -5159,49 +2818,40 @@ "portable", "shim" ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" - }, - "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": "2024-09-09T11:45:10+00:00" + "time": "2017-10-11T12:05:26+00:00" }, { - "name": "symfony/process", - "version": "v6.4.20", + "name": "symfony/polyfill-xml", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "e2a61c16af36c9a07e5c9906498b73e091949a20" + "url": "https://github.com/symfony/polyfill-xml.git", + "reference": "64b6a864f18ab4fddad49f5025f805f6781dfabd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e2a61c16af36c9a07e5c9906498b73e091949a20", - "reference": "e2a61c16af36c9a07e5c9906498b73e091949a20", + "url": "https://api.github.com/repos/symfony/polyfill-xml/zipball/64b6a864f18ab4fddad49f5025f805f6781dfabd", + "reference": "64b6a864f18ab4fddad49f5025f805f6781dfabd", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=5.3.3" + }, + "suggest": { + "ext-xml": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, "autoload": { "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Polyfill\\Xml\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5210,73 +2860,53 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Executes commands in sub-processes", + "description": "Symfony polyfill for xml's utf8_encode and utf8_decode functions", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v6.4.20" - }, - "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" - } + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" ], - "time": "2025-03-10T17:11:00+00:00" + "time": "2016-11-14T01:06:16+00:00" }, { - "name": "symfony/service-contracts", - "version": "v3.5.1", + "name": "symfony/process", + "version": "v4.0.3", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "url": "https://github.com/symfony/process.git", + "reference": "2145b3e8137e463b1051b79440a59b38220944f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/process/zipball/2145b3e8137e463b1051b79440a59b38220944f0", + "reference": "2145b3e8137e463b1051b79440a59b38220944f0", "shasum": "" }, "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" + "php": "^7.1.3" }, "type": "library", "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-master": "4.0-dev" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" + "Symfony\\Component\\Process\\": "" }, "exclude-from-classmap": [ - "/Test/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5285,62 +2915,41 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Symfony Process Component", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" - }, - "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": "2024-09-25T14:20:29+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.19", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c" + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", - "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d52321f0e2b596bd03b5d1dd6eebe71caa925704", + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/service-contracts": "^2.5|^3" + "php": "^7.1.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" @@ -5363,65 +2972,42 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a way to profile code", + "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.19" - }, - "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": "2025-02-21T10:06:30+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { - "name": "symfony/string", - "version": "v6.4.15", + "name": "symfony/yaml", + "version": "v3.2.6", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" + "url": "https://github.com/symfony/yaml.git", + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", - "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" + "php": ">=5.5.9" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, "autoload": { - "files": [ - "Resources/functions.php" - ], "psr-4": { - "Symfony\\Component\\String\\": "" + "Symfony\\Component\\Yaml\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -5433,67 +3019,44 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.4.15" - }, - "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": "2024-11-13T13:31:12+00:00" + "time": "2017-03-07T16:47:02+00:00" }, { "name": "tecnickcom/tcpdf", - "version": "6.10.0", + "version": "6.2.12", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "ca5b6de294512145db96bcbc94e61696599c391d" + "reference": "2f732eaa91b5665274689b1d40b285a7bacdc37f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/ca5b6de294512145db96bcbc94e61696599c391d", - "reference": "ca5b6de294512145db96bcbc94e61696599c391d", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/2f732eaa91b5665274689b1d40b285a7bacdc37f", + "reference": "2f732eaa91b5665274689b1d40b285a7bacdc37f", "shasum": "" }, "require": { - "ext-curl": "*", - "php": ">=7.1.0" + "php": ">=5.3.0" }, "type": "library", "autoload": { "classmap": [ + "fonts", "config", "include", "tcpdf.php", + "tcpdf_parser.php", + "tcpdf_import.php", "tcpdf_barcodes_1d.php", "tcpdf_barcodes_2d.php", "include/tcpdf_colors.php", @@ -5509,13 +3072,13 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "LGPLv3" ], "authors": [ { "name": "Nicola Asuni", "email": "info@tecnick.com", - "role": "lead" + "homepage": "http://nicolaasuni.tecnick.com" } ], "description": "TCPDF is a PHP class for generating PDF documents and barcodes.", @@ -5529,81 +3092,70 @@ "pdf417", "qrcode" ], - "support": { - "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.10.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/donate/?hosted_button_id=NZUEC5XS8MFBJ", - "type": "custom" - } - ], - "time": "2025-05-27T18:02:28+00:00" + "time": "2015-09-12T10:08:34+00:00" }, { - "name": "theseer/tokenizer", - "version": "1.2.3", + "name": "webmozart/assert", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Webmozart\\Assert\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2016-11-23T20:04:58+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": { - "dealerdirect/phpcodesniffer-composer-installer": 20 + "friendsofphp/php-cs-fixer": 0 }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^8.1", + "php": "^5.6|^7.0", "ext-ctype": "*", "ext-dom": "*", - "ext-fileinfo": "*", "ext-gd": "*", "ext-iconv": "*", "ext-libxml": "*", @@ -5615,9 +3167,5 @@ "ext-zip": "*", "ext-zlib": "*" }, - "platform-dev": [], - "platform-overrides": { - "php": "8.1.99" - }, - "plugin-api-version": "2.6.0" + "platform-dev": [] } diff --git a/docs/assets/ClassDiagrams/Architecture.cd b/docs/assets/ClassDiagrams/Architecture.cd new file mode 100644 index 0000000000..afc1dbd094 --- /dev/null +++ b/docs/assets/ClassDiagrams/Architecture.cd @@ -0,0 +1,51 @@ + + + + + + + Classes\PHPExcel.cs + AAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAA= + + + + + + + + + Classes\Worksheet.cs + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + + + + + + Classes\IReader.cs + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + + + + + + + + + + + + + + Classes\IWriter.cs + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/ClassDiagrams/Architecture.png b/docs/assets/ClassDiagrams/Architecture.png new file mode 100644 index 0000000000..3fc7655a96 Binary files /dev/null and b/docs/assets/ClassDiagrams/Architecture.png differ diff --git a/docs/assets/ClassDiagrams/ClassDiagrams.csproj b/docs/assets/ClassDiagrams/ClassDiagrams.csproj new file mode 100644 index 0000000000..7ee02eeb5f --- /dev/null +++ b/docs/assets/ClassDiagrams/ClassDiagrams.csproj @@ -0,0 +1,64 @@ + + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {CC8CD7D2-8EFF-48E5-A17A-C1C482744D31} + Exe + Properties + ClassDiagrams + ClassDiagrams + + + 2.0 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/ClassDiagrams/ClassDiagrams.csproj.user b/docs/assets/ClassDiagrams/ClassDiagrams.csproj.user new file mode 100644 index 0000000000..6a34e7dcdf --- /dev/null +++ b/docs/assets/ClassDiagrams/ClassDiagrams.csproj.user @@ -0,0 +1,5 @@ + + + ShowAllFiles + + \ No newline at end of file diff --git a/docs/assets/ClassDiagrams/ClassDiagrams.sln b/docs/assets/ClassDiagrams/ClassDiagrams.sln new file mode 100644 index 0000000000..3ed77321c0 --- /dev/null +++ b/docs/assets/ClassDiagrams/ClassDiagrams.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassDiagrams", "ClassDiagrams.csproj", "{CC8CD7D2-8EFF-48E5-A17A-C1C482744D31}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CC8CD7D2-8EFF-48E5-A17A-C1C482744D31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC8CD7D2-8EFF-48E5-A17A-C1C482744D31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC8CD7D2-8EFF-48E5-A17A-C1C482744D31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC8CD7D2-8EFF-48E5-A17A-C1C482744D31}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/docs/assets/ClassDiagrams/Classes/IReader.cs b/docs/assets/ClassDiagrams/Classes/IReader.cs new file mode 100644 index 0000000000..96c11afbc6 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/IReader.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public interface PHPExcel_Reader_IReader + { + PHPExcel reads + { + get; + set; + } + } +} diff --git a/docs/assets/ClassDiagrams/Classes/IWriter.cs b/docs/assets/ClassDiagrams/Classes/IWriter.cs new file mode 100644 index 0000000000..d1d6642574 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/IWriter.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public interface PHPExcel_Writer_IWriter + { + PHPExcel writes + { + get; + set; + } + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel.cs new file mode 100644 index 0000000000..5efaa5bd47 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel + { + /// + public Worksheet Worksheets + { + get + { + throw new System.NotImplementedException(); + } + set + { + } + } + } + + public class PHPExcel_Writer_PDF : PHPExcel_Writer_IWriter + { + #region PHPExcel_Writer_IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_IOFactory.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_IOFactory.cs new file mode 100644 index 0000000000..523748b9c4 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_IOFactory.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_IOFactory + { + public PHPExcel_Reader_IReader createsReader + { + get + { + throw new System.NotImplementedException(); + } + set + { + } + } + + public PHPExcel_Writer_IWriter createsWriter + { + get + { + throw new System.NotImplementedException(); + } + set + { + } + } + + public PHPExcel_Writer_IWriter createWriter() + { + throw new System.NotImplementedException(); + } + + public PHPExcel_Reader_IReader createReader() + { + throw new System.NotImplementedException(); + } + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel2007.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel2007.cs new file mode 100644 index 0000000000..5cf6e3df0f --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel2007.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_Reader_Excel2007 : PHPExcel_Reader_IReader + { + #region IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel5.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel5.cs new file mode 100644 index 0000000000..e40721215d --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Excel5.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_Reader_Excel5 : PHPExcel_Reader_IReader + { + #region PHPExcel_Writer_IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Reader_Excel2003XML : PHPExcel_Reader_IReader + { + #region PHPExcel_Writer_IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Reader_SYLK : PHPExcel_Reader_IReader + { + #region PHPExcel_Writer_IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Serialized.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Serialized.cs new file mode 100644 index 0000000000..ea114c88da --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_Reader_Serialized.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_Reader_Serialized : PHPExcel_Reader_IReader + { + #region IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Reader_CSV : PHPExcel_Reader_IReader + { + #region IReader Members + + public PHPExcel reads + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Excel2007.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Excel2007.cs new file mode 100644 index 0000000000..03edda934a --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Excel2007.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_Writer_Excel2007 : PHPExcel_Writer_IWriter + { + #region IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Serialized.cs b/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Serialized.cs new file mode 100644 index 0000000000..cf8af208a7 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/PHPExcel_Writer_Serialized.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class PHPExcel_Writer_Serialized : PHPExcel_Writer_IWriter + { + #region IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Writer_CSV : PHPExcel_Writer_IWriter + { + #region IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Writer_Excel5 : PHPExcel_Writer_IWriter + { + #region IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } + + public class PHPExcel_Writer_HTML : PHPExcel_Writer_IWriter + { + #region IWriter Members + + public PHPExcel writes + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + #endregion + } +} diff --git a/docs/assets/ClassDiagrams/Classes/Worksheet.cs b/docs/assets/ClassDiagrams/Classes/Worksheet.cs new file mode 100644 index 0000000000..fdcf0ff764 --- /dev/null +++ b/docs/assets/ClassDiagrams/Classes/Worksheet.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ClassDiagrams +{ + public class Worksheet + { + } + + public class CopyOfWorksheet + { + } +} diff --git a/docs/assets/ClassDiagrams/Exports/Architecture.png b/docs/assets/ClassDiagrams/Exports/Architecture.png new file mode 100644 index 0000000000..1324818030 Binary files /dev/null and b/docs/assets/ClassDiagrams/Exports/Architecture.png differ diff --git a/docs/assets/ClassDiagrams/Exports/ReaderWriter.png b/docs/assets/ClassDiagrams/Exports/ReaderWriter.png new file mode 100644 index 0000000000..b915faa7c6 Binary files /dev/null and b/docs/assets/ClassDiagrams/Exports/ReaderWriter.png differ diff --git a/docs/assets/ClassDiagrams/ReaderWriter.cd b/docs/assets/ClassDiagrams/ReaderWriter.cd new file mode 100644 index 0000000000..bbaf291209 --- /dev/null +++ b/docs/assets/ClassDiagrams/ReaderWriter.cd @@ -0,0 +1,135 @@ + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Excel2007.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel_Writer_Excel2007.cs + + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel_Writer_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel_Writer_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel_Writer_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel_Writer_Serialized.cs + + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Excel5.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\PHPExcel.cs + + + + + + + + + + + + + + + + + AIAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAABAAAAAAA= + Classes\PHPExcel_IOFactory.cs + + + + + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Excel5.cs + + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\PHPExcel_Reader_Excel5.cs + + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA= + Classes\IWriter.cs + + + + + + AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAA= + Classes\IReader.cs + + + + \ No newline at end of file diff --git a/docs/assets/ClassDiagrams/ReaderWriter.png b/docs/assets/ClassDiagrams/ReaderWriter.png new file mode 100644 index 0000000000..d76c98d988 Binary files /dev/null and b/docs/assets/ClassDiagrams/ReaderWriter.png differ diff --git a/docs/extra/extra.css b/docs/extra/extra.css index 704819d7a3..2addeb79e4 100644 --- a/docs/extra/extra.css +++ b/docs/extra/extra.css @@ -6,14 +6,3 @@ table.features-cross-reference { .rst-content table.features-cross-reference.docutils td { background-color: white; } - -/* https://github.com/mkdocs/mkdocs/discussions/3035#discussioncomment-7237037 */ -.wy-table-responsive table td, .wy-table-responsive table th { - white-space: normal !important; -} -.wy-table-responsive { - overflow : visible !important; -} - -/* https://github.com/readthedocs/sphinx_rtd_theme/issues/295#issuecomment-455226058 */ -.wy-nav-content {max-width: none;} diff --git a/docs/extra/extrajs.js b/docs/extra/extrajs.js deleted file mode 100644 index 9ad135e838..0000000000 --- a/docs/extra/extrajs.js +++ /dev/null @@ -1,5 +0,0 @@ -document.addEventListener("DOMContentLoaded", function() { - document.querySelectorAll("table").forEach(function(table) { - table.classList.add("docutils"); - }); -}); \ No newline at end of file diff --git a/docs/faq.md b/docs/faq.md index cc44ade699..19f5f8fc2f 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -23,7 +23,7 @@ When you make use of any of the worksheet protection features (e.g. cell range protection, prohibiting deleting rows, ...), make sure you enable worksheet security. This can for example be done like this: -```php +``` php $spreadsheet->getActiveSheet()->getProtection()->setSheet(true); ``` @@ -55,7 +55,3 @@ file in Excel, the actual width is 0.71 less than it should be. The short answer is that PhpSpreadsheet uses a measure where padding is included. See [how to set a column's width](./topics/recipes.md#setting-a-columns-width) for more details. - -## I cannot serialize or json_encode my Spreadsheet - -No, you can't. Consider the Spreadsheet object as a PHP resource, which cannot be serialized. diff --git a/docs/index.md b/docs/index.md index a4b87d32a3..08a91995d5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,8 +2,9 @@ ![Logo](./assets/logo.svg) -PhpSpreadsheet is a library written in pure PHP and offers a set of classes that -allow you to read and write various spreadsheet file formats such as Excel and LibreOffice Calc. +PhpSpreadsheet is a library written in pure PHP and providing a set of +classes that allow you to read from and to write to different +spreadsheet file formats, like Excel and LibreOffice Calc. ## File formats supported @@ -20,91 +21,31 @@ allow you to read and write various spreadsheet file formats such as Excel and L |CSV | ✓ | ✓ | |PDF (using either the TCPDF, Dompdf or mPDF libraries, which need to be installed separately)| | ✓ | -Note - reading or writing certain aspects of a spreadsheet may not be supported in all formats. For more details, please consult -[Features Cross-reference](./references/features-cross-reference.md). - # Getting started ## Software requirements -PHP version 8.1 or newer to develop using PhpSpreadsheet. Other requirements, such as PHP extensions, are enforced by -composer. See the `require` section of [the composer.json file](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/composer.json) -for details. - -### PHP version support - -LTS: Support for PHP versions will only be maintained for a period of six months beyond the -[end of life of that PHP version](https://www.php.net/eol.php). +The following software is required to develop using PhpSpreadsheet: -Currently, the required PHP minimum version is __PHP 8.1__, and we [will support that version](https://www.php.net/eol.php) until June 2026. +- PHP version 5.6 or newer +- PHP extension php\_zip enabled +- PHP extension php\_xml enabled +- PHP extension php\_gd2 enabled (if not compiled in) -Support for PHP versions will only be maintained for a period of six months beyond the -[end of life](https://www.php.net/supported-versions) of that PHP version. +### PHP version support -See the `composer.json` for other requirements. +Support for PHP versions will only be maintained for a period of six months beyond the end-of-life of that PHP version ## Installation -Use [composer](https://getcomposer.org) to install PhpSpreadsheet into your project: +Use [composer](https://getcomposer.org/) to install PhpSpreadsheet into your project: ```sh composer require phpoffice/phpspreadsheet ``` -Or also download the documentation and samples if you plan to use them (note that `git` must be in your path for this to work): - -```sh -composer require phpoffice/phpspreadsheet --prefer-source -``` - -If you are building your installation on a development machine that is on a different PHP version to the server where it -will be deployed, or if your PHP CLI version is different from your run-time such as `php-fpm` or Apache's `mod_php`, -then you might want to configure composer for that. -See [composer documentation](https://getcomposer.org/doc/06-config.md#platform) -on how to edit your `composer.json` to ensure that the correct dependencies are retrieved to match your deployment -environment. - -See [CLI vs Application run-time](https://php.watch/articles/composer-platform-check) for more details. - -### Additional Installation Options - -If you want to write to PDF, or to include Charts when you write to HTML or PDF, then you will need to install additional libraries: - -#### PDF - -For PDF Generation, you can install any of the following, and then configure PhpSpreadsheet to indicate which library you are going to use: -- mpdf/mpdf -- dompdf/dompdf -- tecnickcom/tcpdf - -and configure PhpSpreadsheet using: - -```php -// Dompdf, Mpdf or Tcpdf (as appropriate) -$className = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class; -IOFactory::registerWriter('Pdf', $className); -``` -or the appropriate PDF Writer wrapper for the library that you have chosen to install. - -#### Chart Export - -For Chart export, we support following packages, which you will also need to install yourself using `composer require` -- [jpgraph/jpgraph](https://packagist.org/packages/jpgraph/jpgraph) (this package was abandoned at version 4.0. - You can manually download the latest version that supports PHP 8 and above from [jpgraph.net](https://jpgraph.net/)) -- [mitoteam/jpgraph](https://packagist.org/packages/mitoteam/jpgraph) - up to date fork with modern PHP versions support and some bugs fixed. - -and then configure PhpSpreadsheet using: -```php -// to use jpgraph/jpgraph -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); -//or -// to use mitoteam/jpgraph -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); -``` - -One or the other of these libraries is necessary if you want to generate HTML or PDF files that include charts; or to render a Chart to an Image format from within your code. -They are not necessary to define charts for writing to `Xlsx` files. -Other file formats don't support writing Charts. +**Note:** If you want the unreleased, unstable development version use +`phpoffice/phpspreadsheet:dev-develop` instead. ## Hello World @@ -119,8 +60,8 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; $spreadsheet = new Spreadsheet(); -$activeWorksheet = $spreadsheet->getActiveSheet(); -$activeWorksheet->setCellValue('A1', 'Hello World !'); +$sheet = $spreadsheet->getActiveSheet(); +$sheet->setCellValue('A1', 'Hello World !'); $writer = new Xlsx($spreadsheet); $writer->save('hello world.xlsx'); @@ -128,8 +69,8 @@ $writer->save('hello world.xlsx'); ## Learn by example -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: +A good way to get started is to run some of the samples. Serve the samples via +PHP built-in webserver: ```sh php -S localhost:8000 -t vendor/phpoffice/phpspreadsheet/samples @@ -147,14 +88,14 @@ php vendor/phpoffice/phpspreadsheet/samples/Basic/01_Simple.php ## Learn by documentation -For more documentation in depth, you may read about an [overview of the +For more in-depth documentation, you may read about an [overview of the architecture](./topics/architecture.md), [creating a spreadsheet](./topics/creating-spreadsheet.md), [worksheets](./topics/worksheets.md), [accessing cells](./topics/accessing-cells.md) and [reading and writing to files](./topics/reading-and-writing-to-file.md). -Or browse the [API documentation](https://phpoffice.github.io/PhpSpreadsheet). +Or browse the [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master). # Credits diff --git a/docs/references/features-cross-reference.md b/docs/references/features-cross-reference.md index c431def44b..efd3f23cd9 100644 --- a/docs/references/features-cross-reference.md +++ b/docs/references/features-cross-reference.md @@ -5,12 +5,12 @@ - ✖ Not supported - N/A Cannot be supported -## Readers - - + + + @@ -21,29 +21,50 @@ + + + + + + + - + - + - + + + + + + + + - + - + + + + + + + + @@ -54,7 +75,14 @@ - + + + + + + + + @@ -63,12 +91,19 @@ - - - + + + + + + + + + + - + @@ -76,10 +111,17 @@ + + + + + + + - + @@ -88,6 +130,13 @@ + + + + + + + @@ -99,6 +148,13 @@ + + + + + + + @@ -110,6 +166,13 @@ + + + + + + + @@ -121,6 +184,13 @@ + + + + + + + @@ -132,6 +202,13 @@ + + + + + + + @@ -143,6 +220,13 @@ + + + + + + + @@ -154,6 +238,13 @@ + + + + + + + @@ -165,6 +256,13 @@ + + + + + + + @@ -176,9 +274,16 @@ + + + + + + + - + @@ -186,7 +291,14 @@ + + + + + + + @@ -197,7 +309,14 @@ + + + + + + + @@ -208,7 +327,14 @@ + + + + + + + @@ -219,10 +345,17 @@ + + + + + + + - + @@ -230,7 +363,14 @@ + + + + + + + @@ -241,7 +381,14 @@ + + + + + + + @@ -252,7 +399,14 @@ + + + + + + + @@ -263,7 +417,14 @@ + + + + + + + @@ -274,12 +435,26 @@ + + + + + + + - + + + + + + + + @@ -289,742 +464,51 @@ + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ReadersReadersWritersMethods
Gnumeric CSV SYLKXLSXLSXOdsCSV HTMLPDFGettersSetters
Reader OptionsReader Options ✔ ✔ â—â— 6◠✔ N/A N/A✔N/AN/AN/AN/AN/AN/A
Read Data Only (no formatting) ✔ ✔ ✖✔✖ ✔ N/A N/A✔N/AN/AN/AN/AN/AN/A$reader->getReadDataOnly()$reader->setReadDataOnly()
Read Only Specified Worksheets✔ N/A N/A✔N/AN/AN/AN/AN/AN/A$reader->getLoadSheetsOnly()$reader->setLoadSheetsOnly()
$reader->setLoadAllSheets()
Read Only Specified Cells✔ ✔ ✔✔✖✔N/AN/AN/AN/AN/AN/AN/AN/A$reader->getReadFilter()$reader->setReadFilter()
Document PropertiesDocument Properties ◠✔ ✔✔ N/A N/Aâ—✔ ✔N/AN/Aâ—
Standard PropertiesStandard Properties ✔ ✔ ✔N/A N/A ✔✔â—N/AN/Aâ—
CreatorN/A N/A ✔✔✔N/A✔✔$spreadsheet->getProperties()->getCreator()$spreadsheet->getProperties()->setCreator()
Creation Date/TimeN/A N/A ✔✔✔N/AN/A✖$spreadsheet->getProperties()->getCreated()$spreadsheet->getProperties()->setCreated()
ModifierN/A N/A ✔✔✖N/AN/A✖$spreadsheet->getProperties()->getLastModifiedBy()$spreadsheet->getProperties()->setLastModifiedBy()
Modified Date/TimeN/A N/A ✔✔✖N/AN/A✖$spreadsheet->getProperties()->getModified()$spreadsheet->getProperties()->setModified()
TitleN/A N/A ✔✔✔N/A✔✔$spreadsheet->getProperties()->getTitle()$spreadsheet->getProperties()->setTitle()
DescriptionN/A N/A ✔✔✔N/AN/A✖$spreadsheet->getProperties()->getDescription()$spreadsheet->getProperties()->setDescription()
SubjectN/A N/A ✔✔✔N/A✔✔$spreadsheet->getProperties()->getSubject()$spreadsheet->getProperties()->setSubject()
KeywordsN/A N/A ✔✔✔N/A✔✔$spreadsheet->getProperties()->getKeywords()$spreadsheet->getProperties()->setKeywords()
Extended PropertiesExtended Properties ✔ ✔ ✔✔ N/A N/A ✔â—N/AN/A
Category✔ N/A N/A ✔✔N/AN/A$spreadsheet->getProperties()->getCategory()$spreadsheet->getProperties()->setCategory()
Company✔ N/A N/A✔ ✔N/AN/A$spreadsheet->getProperties()->getCompany()$spreadsheet->getProperties()->setCompany()
Manager✔ N/A N/A ✔✖N/AN/A$spreadsheet->getProperties()->getManager()$spreadsheet->getProperties()->setManager()
User-Defined (Custom) PropertiesUser-Defined (Custom) Properties ✖ ✔ ✔N/A N/A N/A ✔✖N/AN/A$spreadsheet->getProperties()->getCustomProperties()
$spreadsheet->getProperties()->isCustomPropertySet()
$spreadsheet->getProperties()->getCustomPropertyValue()
$spreadsheet->getProperties()->getCustomPropertyType()
$spreadsheet->getProperties()->setCustomProperty()
Text PropertiesN/A N/A N/A ✔✖N/AN/A
Number PropertiesN/A N/A N/A ✔✖N/AN/A
Date PropertiesN/A N/A N/A ✔✖N/AN/A
Yes/No (Boolean) PropertiesN/A N/A N/A ✔✖N/AN/A
Cell Data TypesCell Data Typesâ— â—
Empty/NULL ✔✔✔✔✔✔✔✔
Boolean ✔✔✔✔✔✔✔✔
Integer ✔✔✔✔✔✔✔✔
Floating Point✔✔✔✔✔✔✔✔
String✔✔✔✔✔✔✔✔
Error✔✔✔✔✔✔✔✔
Formula✔✔✔✔✔✖✔✖
Array Formula✖✔✔✔✔N/A✖N/A
Rich Text✔✔✔✔✔✖✖✖
Conditional Formatting✔✔✖✖✖N/AN/A✖
Rows and Column Properties✔✔✔✖✔N/AN/A✔
Row Height/Column Width✔✔✔✔✔N/AN/A✔
Hidden✔✔✔✖✔N/AN/A✔
Worksheet Propertiesâ—✔â—â—✖N/AN/Aâ—
Frozen Panes✔✔✔✖✖N/AN/AN/A
Hidden Worksheets✔✔✖✔✖N/AN/Aâ—
Coloured Tabs✖✔✖✖✖N/AN/AN/A
Drawing hyperlink✖✔✖✖✖N/AN/A✔
Cell Formatting✔✔â—â—✔N/Aâ—â— 7
Number Format Mask✔✔✔â—✔N/A✔✔
Alignment✔✔✔✖✔N/A✖◠7
Horizontal✔✔✔✖✔N/A✖✔
Vertical✔✔✔✖✔N/A✖✔
Wrapping✔✔✔✖✔N/A✖â—
Shrink-to-Fit✔✔✔✖✔N/A✖â—
Indent✔✔✖✖✔N/A✖✔
Background Colour✔✔✔✖✔N/A✔◠7
Patterned✔✔✔✖✔N/A✔✖
Font Attributes✔✔✔✖✔N/A✔◠7
Font Face✔✔✔✖✔N/A✔✔
Font Size✔✔✔✖✔N/A✔✔
Bold✔✔✔✖✔N/A✔✔
Italic✔✔✔✖✔N/A✔✔
Strikethrough✔✔✔✖✔N/A✔✔
Underline✔✔✔✖✔N/A✔✔
Superscript✔✔✔✖✔N/A✔✔
Subscript✔✔✔✖✔N/A✔✔
Borders✔✔✔✖✔N/Aâ—â— 7
Line Style✔✔✔✖✔N/A✔✔
Position✔✔✔✖✔N/A✔✔
Diagonal✔✔✔✖✔N/A✖✖
Hyperlinks✔✔✔✔✔✖✖✔
http✔✔✔✔✔N/A✖✔
Merged Cells✔✔✔✔✔N/A✖✔
Cell Commentsâ—â—â—â—â—N/Aâ—â—
Rich Text✖ 2✔✖✖â—N/AN/A✖
Alignment✖ 3✔✖✖✖N/A✖✔
Background Image✖✔✖✖✖N/A✖✖
Cell Validation✔✔✖✖✖N/AN/AN/A
AutoFiltersâ—â—â—â—â—N/AN/AN/A
AutoFilter Expressions✔✔✔✔✔N/AN/AN/A
Filter✔✔✔✔✔N/AN/AN/A
Custom Filter✔✔✔✔✔N/AN/AN/A
Date Filter✔✔✔✔✔N/AN/AN/A
Dynamic Filter✔✔✔✔✔N/AN/AN/A
Colour Filter✖✖✖✖✖N/AN/AN/A
Icon Filter✖✖✖✖✖N/AN/AN/A
Top 10 Filter✖✔✖✖✖N/AN/AN/A
Macros✖◠5 - ✖✖✖✖✖✖
Form Controls✖◠4 - ✖✖✖✖✖✖
Securityâ—â—✖✖✖✖✖✖
Protection (prevent editing)✔✔✖✖✖✖✖✖
Encryption (prevent viewing)✖✖✖✖✖✖✖✖
XLSXLSXExcel2003XMLOdsGnumericCSVSYLKHTML
Readers
- -1. Only text contents -2. Only BIFF8 files support Rich Text. Prior to that, comments could only be plain text -3. Only BIFF8 files support alignment and rotation. Prior to that, comments could only be unformatted text -4. Xlsx forms and controls can be read and written but not otherwise manipulated -5. Xlsx macros can be read and written; their values can be retrieved and changed, but only in a binary form which is unlikely to be useful -6. There is very limited support for reading styles from an Ods spreadsheet. Writing styles has better support, although Number Format is incomplete. -7. In most cases, Html reader processes only inline styles; styles provided by Css classes may be ignored. -8. Code must [opt in](../topics/recipes.md#array-formulas) to array output. - -## Writers - - - - - - - - - - - - - - - - - + + + + @@ -1033,88 +517,16 @@ - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1123,70 +535,124 @@ - - - - - - - - - - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + - + + + + + + + + + + - - - + + + + + - - - + + + + + + + + + + - + + + + + - - + + + + + + + - + + + + + + + - - - + + + + + + - + + + + + + + + + + @@ -1196,24 +662,33 @@ + + + + - - - - - + + + + + + + + + + + + + + - - - - - - - - + + + + @@ -1222,43 +697,88 @@ - - - - - - + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + - - - + + + + - - + + + + + + + + + + - - + + - - - - + + + + + + + + + + + + + - + + + + + + + + + + @@ -1270,82 +790,163 @@ - - - + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + @@ -1353,83 +954,209 @@ + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + - - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - - + + + + @@ -1438,106 +1165,178 @@ - - - - - - + + + + + + + + + + + + + + + - - + - - - - - - - - - - - + + + - - - - - - + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + - + + + + + + + + - + + + - + - - - - + + - + + + - + + - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + @@ -1546,297 +1345,247 @@ - - + + + + + + + + - - - + + + + + + - - + + + + + + + + - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + - - - + + + + + + - - + + + + + + + + - - - - - - - - - + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - + + + + + + + + + + + + + + - - - - - -
Writers
XLSXLSXOdsCSVHTMLPDF
Document Properties
Standard PropertiesFloating Point ✔
Creator✔✔✔N/A✔✔
Creation Date/Time✔✔✔N/A✔✖
Modifier✔✔✖N/A✔✖
Modified Date/Time✔✔✖N/A✔✖
Title✔✔✔N/A✔✔
Description✔✔✔N/A✔✖
Subject✔✔✔N/A✔✔
Keywords✔✔✔N/A✔✔
Extended Properties
Category✔✔✖N/A✔✖
Company✖✔✖N/AString ✔✖
Manager✖✔✖N/AError ✔✖
User-Defined (Custom) Properties✖✔✔N/AFormula ✔N/A
Rich Text✔✔Array ✖N/A✔✔
Conditional FormattingRich Text ✔ ✔ ✖N/A ✖✖✖✔N/A
Array Formula8Conditional Formatting ✖ ✔N/A✖ ✔✔✔✔N/A
Rows and Column PropertiesRows and Column Properties✔
Row Height/Column Width ✔✔✔N/A✔✔
Hidden ✔✔✖N/A✔✔
Worksheet Properties
Frozen Panesâ—✔✖N/A✔Worksheet Properties ✖
Hidden Worksheetsâ—✔✖N/A✔Frozen Panes ✖
Coloured Tabs✖✔✖ N/A✖✖
Drawing hyperlink✖Drawing hyperlink ✔✖N/A✖✖✔$drawing->getHyperlink()->getUrl()$drawing->setHyperlink()->setUrl($url)
Cell FormattingCell Formattingâ— Number Format Mask ✔ ✔â—N/A✔ ✔
Alignment ✔✔✔N/A✔✔
Horizontal ✔✔✔N/A✔✔
Vertical ✔✔✔N/A✔✔
Wrapping ✔✔✔N/A✔✔
Shrink-to-Fit✔✔✔N/A✔Shring-to-Fit ✔
Indent ✔✔✔N/A✔✔
Background Colour ✔✔✔N/A✔✔â—
Patterned ✔✔✔N/A✔✔
Font Attributes ✔â—
Font Face ✔ ✔✔N/A✔✔
Font Size ✔ ✔✔N/A✔✔
Bold ✔ ✔✔N/A✔✔
Italic ✔ ✔✔N/A✔✔
Strikethrough ✔✔✔N/A✔✔✖
Underline ✔ ✔✔N/A✔✔
Superscript ✔✔✔N/A✔✔✖
Subscript ✔✖
Borders ✔
Line Style ✔N/A✔
Position ✔
Borders
Line Style✔✔✔N/A✔Diagonal ✔
Position✔Hyperlinks ✔ ✔N/A✔ ✔
Diagonal✖ ✔ ✖N/A ✖ ✖
Hyperlinks ✔ ✔ ✖N/A✖ ✔ ✖$cell->getHyperlink()->getUrl($url)$cell->getHyperlink()->setUrl($url)
http✔✔✖N/A✔http ✖
Merged Cells✔✔✔N/A✔Merged Cells ✔
Cell CommentsCell Commentsâ—â—â—â—✔N/AN/A ✖ â— â— N/Aâ— 1â— 1 N/A
Rich Text✖✖ 2 ✔ ✖N/A ✖ N/A
AlignmentN/AN/A ✖ ✔ ✖ N/A✔ N/A
Background ImageAlignment✖ 3 ✖✔ ✖ ✖N/AN/AN/A✖ ✖ ✖N/AN/A
Cell ValidationCell Validation✔✔✖✖✖N/AN/A ✔ ✔ ✖ N/A N/A N/A$cell->getDataValidation()$cell->setDataValidation()
AutoFiltersâ—â—â—â—$sheet->getAutoFilter()$sheet->setAutoFilter()
AutoFiltersAutoFilter Expressions✖â—✖â—
AutoFilter Expressions✔Filter✖ ✔✖ ✔N/AN/AN/A
Filter✔Custom Filter✖ ✔✖ ✔N/AN/AN/A
Custom FilterDateGroup Filter✖✔✖ ✔
Dynamic Filter✖ ✔✖ ✔N/AN/AN/A
Colour Filter✖✖✖✖
Icon Filter✖✖✖✖
DateGroup Filter✔Top 10 Filter✖ ✔✖ ✔N/AN/AN/A
Dynamic Filter✔Macros✖ ✔✖✖✖✖✖✖ ✔N/AN/AN/A
Colour Filter ✖ ✖ ✖N/AN/AN/A✖$spreadsheet->getMacrosCode();$spreadsheet->setMacrosCode();
Icon FilterForm Controls✖✖ ✖ ✖ ✖N/AN/AN/A
Top 10 Filter ✖✔ ✖N/AN/AN/A
Macros ✖◠5 ✖N/A ✖ ✖
Form Controls ✖◠4 ✖N/A ✖ ✖
SecuritySecurityâ—â—✖✖✖✖✖✖✖✖✖✖✖✖✖
Protection (prevent editing) ✔ ✔ ✖N/A ✖ ✖✖✖✔✔✖✖✖✖$sheet->getProtection()$sheet->getProtection()->setSheet(true)
Encryption (prevent viewing)✔✖✖ ✖ ✖ ✖N/A ✖ ✖✖✖✖✖✖
XLS XLSXExcel2003XMLOdsGnumericCSVSYLKXLSXLSX Ods CSV HTML PDF
Writers
- -## Setters and Getters - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
Methods
GettersSetters
Reader Options
Read Data Only (no formatting)$reader->getReadDataOnly()$reader->setReadDataOnly()
Read Only Specified Worksheets$reader->getLoadSheetsOnly()$reader->setLoadSheetsOnly()
$reader->setLoadAllSheets()
Read Only Specified Cells$reader->getReadFilter()$reader->setReadFilter()
Document Properties
Standard Properties
Creator$spreadsheet->getProperties()->getCreator()$spreadsheet->getProperties()->setCreator()
Creation Date/Time$spreadsheet->getProperties()->getCreated()$spreadsheet->getProperties()->setCreated()
Modifier$spreadsheet->getProperties()->getLastModifiedBy()$spreadsheet->getProperties()->setLastModifiedBy()
Modified Date/Time$spreadsheet->getProperties()->getModified()$spreadsheet->getProperties()->setModified()
Title$spreadsheet->getProperties()->getTitle()$spreadsheet->getProperties()->setTitle()
Description$spreadsheet->getProperties()->getDescription()$spreadsheet->getProperties()->setDescription()
Subject$spreadsheet->getProperties()->getSubject()$spreadsheet->getProperties()->setSubject()
Keywords$spreadsheet->getProperties()->getKeywords()$spreadsheet->getProperties()->setKeywords()
Extended Properties
Category$spreadsheet->getProperties()->getCategory()$spreadsheet->getProperties()->setCategory()
Company$spreadsheet->getProperties()->getCompany()$spreadsheet->getProperties()->setCompany()
Manager$spreadsheet->getProperties()->getManager()$spreadsheet->getProperties()->setManager()
User-Defined (Custom) Properties$spreadsheet->getProperties()->getCustomProperties()
$spreadsheet->getProperties()->isCustomPropertySet()
$spreadsheet->getProperties()->getCustomPropertyValue()
$spreadsheet->getProperties()->getCustomPropertyType()
$spreadsheet->getProperties()->setCustomProperty()
$drawing->getHyperlink()->getUrl()$drawing->setHyperlink()->setUrl($url)
$cell->getHyperlink()->getUrl($url)$cell->getHyperlink()->setUrl($url)
Cell Comments
Background Image$comment->getBackgroundImage()$comment->setBackgroundImage()
Cell Validation$cell->getDataValidation()$cell->setDataValidation()
AutoFilters$sheet->getAutoFilter()$sheet->setAutoFilter()
Macros$spreadsheet->getMacrosCode();5$spreadsheet->setMacrosCode();5
Security
Protection (prevent editing)$sheet->getProtection()$sheet->getProtection()->setSheet(true)
Getters Setters
ReadersWriters Methods
+ +1. Only text contents +2. Only BIFF8 files support Rich Text. Prior to that, comments could only be plain text +3. Only BIFF8 files support alignment and rotation. Prior to that, comments could only be unformatted text diff --git a/docs/references/function-list-by-category.md b/docs/references/function-list-by-category.md index 22c5222ad1..185bf4c06f 100644 --- a/docs/references/function-list-by-category.md +++ b/docs/references/function-list-by-category.md @@ -2,595 +2,444 @@ ## CATEGORY_CUBE -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -CUBEKPIMEMBER | **Not yet Implemented** -CUBEMEMBER | **Not yet Implemented** -CUBEMEMBERPROPERTY | **Not yet Implemented** -CUBERANKEDMEMBER | **Not yet Implemented** -CUBESET | **Not yet Implemented** -CUBESETCOUNT | **Not yet Implemented** -CUBEVALUE | **Not yet Implemented** +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +CUBEKPIMEMBER | **Not yet Implemented** +CUBEMEMBER | **Not yet Implemented** +CUBEMEMBERPROPERTY | **Not yet Implemented** +CUBERANKEDMEMBER | **Not yet Implemented** +CUBESET | **Not yet Implemented** +CUBESETCOUNT | **Not yet Implemented** +CUBEVALUE | **Not yet Implemented** ## CATEGORY_DATABASE -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -DAVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DAverage::evaluate -DCOUNT | \PhpOffice\PhpSpreadsheet\Calculation\Database\DCount::evaluate -DCOUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Database\DCountA::evaluate -DGET | \PhpOffice\PhpSpreadsheet\Calculation\Database\DGet::evaluate -DMAX | \PhpOffice\PhpSpreadsheet\Calculation\Database\DMax::evaluate -DMIN | \PhpOffice\PhpSpreadsheet\Calculation\Database\DMin::evaluate -DPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\Database\DProduct::evaluate -DSTDEV | \PhpOffice\PhpSpreadsheet\Calculation\Database\DStDev::evaluate -DSTDEVP | \PhpOffice\PhpSpreadsheet\Calculation\Database\DStDevP::evaluate -DSUM | \PhpOffice\PhpSpreadsheet\Calculation\Database\DSum::evaluate -DVAR | \PhpOffice\PhpSpreadsheet\Calculation\Database\DVar::evaluate -DVARP | \PhpOffice\PhpSpreadsheet\Calculation\Database\DVarP::evaluate +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +DAVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DAVERAGE +DCOUNT | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNT +DCOUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNTA +DGET | \PhpOffice\PhpSpreadsheet\Calculation\Database::DGET +DMAX | \PhpOffice\PhpSpreadsheet\Calculation\Database::DMAX +DMIN | \PhpOffice\PhpSpreadsheet\Calculation\Database::DMIN +DPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\Database::DPRODUCT +DSTDEV | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSTDEV +DSTDEVP | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSTDEVP +DSUM | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSUM +DVAR | \PhpOffice\PhpSpreadsheet\Calculation\Database::DVAR +DVARP | \PhpOffice\PhpSpreadsheet\Calculation\Database::DVARP ## CATEGORY_DATE_AND_TIME -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -DATE | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Date::fromYMD -DATEDIF | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Difference::interval -DATESTRING | **Not yet Implemented** -DATEVALUE | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateValue::fromString -DAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::day -DAYS | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Days::between -DAYS360 | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Days360::between -EDATE | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month::adjust -EOMONTH | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month::lastDay -HOUR | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::hour -ISOWEEKNUM | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::isoWeekNumber -MINUTE | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::minute -MONTH | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::month -NETWORKDAYS | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\NetworkDays::count -NETWORKDAYS.INTL | **Not yet Implemented** -NOW | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Current::now -SECOND | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::second -THAIDAYOFWEEK | **Not yet Implemented** -THAIMONTHOFYEAR | **Not yet Implemented** -THAIYEAR | **Not yet Implemented** -TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Time::fromHMS -TIMEVALUE | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeValue::fromString -TODAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Current::today -WEEKDAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::day -WEEKNUM | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::number -WORKDAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\WorkDay::date -WORKDAY.INTL | **Not yet Implemented** -YEAR | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::year -YEARFRAC | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\YearFrac::fraction +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +DATE | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATE +DATEDIF | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEDIF +DATEVALUE | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEVALUE +DAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYOFMONTH +DAYS360 | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS360 +EDATE | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EDATE +EOMONTH | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EOMONTH +HOUR | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::HOUROFDAY +ISOWEEKNUM | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::ISOWEEKNUM +MINUTE | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MINUTE +MONTH | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MONTHOFYEAR +NETWORKDAYS | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::NETWORKDAYS +NOW | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATETIMENOW +SECOND | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::SECOND +TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIME +TIMEVALUE | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIMEVALUE +TODAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATENOW +WEEKDAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKDAY +WEEKNUM | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKNUM +WORKDAY | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WORKDAY +YEAR | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEAR +YEARFRAC | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEARFRAC ## CATEGORY_ENGINEERING -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -BESSELI | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselI::BESSELI -BESSELJ | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselJ::BESSELJ -BESSELK | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselK::BESSELK -BESSELY | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselY::BESSELY -BIN2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toDecimal -BIN2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toHex -BIN2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toOctal -BITAND | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITAND -BITLSHIFT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITLSHIFT -BITOR | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITOR -BITRSHIFT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITRSHIFT -BITXOR | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITXOR -COMPLEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::COMPLEX -CONVERT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertUOM::CONVERT -DEC2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toBinary -DEC2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toHex -DEC2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toOctal -DELTA | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Compare::DELTA -ERF | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Erf::ERF -ERF.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Erf::ERFPRECISE -ERFC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ErfC::ERFC -ERFC.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ErfC::ERFC -GESTEP | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Compare::GESTEP -HEX2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toBinary -HEX2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toDecimal -HEX2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toOctal -IMABS | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMABS -IMAGINARY | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::IMAGINARY -IMARGUMENT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMARGUMENT -IMCONJUGATE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCONJUGATE -IMCOS | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOS -IMCOSH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOSH -IMCOT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOT -IMCSC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCSC -IMCSCH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCSCH -IMDIV | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMDIV -IMEXP | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMEXP -IMLN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLN -IMLOG10 | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLOG10 -IMLOG2 | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLOG2 -IMPOWER | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMPOWER -IMPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMPRODUCT -IMREAL | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::IMREAL -IMSEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSEC -IMSECH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSECH -IMSIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSIN -IMSINH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSINH -IMSQRT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSQRT -IMSUB | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMSUB -IMSUM | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMSUM -IMTAN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMTAN -OCT2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toBinary -OCT2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toDecimal -OCT2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toHex +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +BESSELI | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELI +BESSELJ | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELJ +BESSELK | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELK +BESSELY | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELY +BIN2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTODEC +BIN2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOHEX +BIN2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOOCT +COMPLEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::COMPLEX +CONVERT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::CONVERTUOM +DEC2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOBIN +DEC2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOHEX +DEC2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOOCT +DELTA | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DELTA +ERF | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERF +ERF.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFPRECISE +ERFC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC +ERFC.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC +GESTEP | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::GESTEP +HEX2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOBIN +HEX2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTODEC +HEX2OCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOOCT +IMABS | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMABS +IMAGINARY | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINARY +IMARGUMENT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT +IMCONJUGATE | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCONJUGATE +IMCOS | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOS +IMCOSH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOSH +IMCOT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOT +IMCSC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSC +IMCSCH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSCH +IMDIV | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMDIV +IMEXP | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMEXP +IMLN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLN +IMLOG10 | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLOG10 +IMLOG2 | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLOG2 +IMPOWER | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPOWER +IMPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPRODUCT +IMREAL | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMREAL +IMSEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSEC +IMSECH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSECH +IMSIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSIN +IMSINH | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSINH +IMSQRT | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSQRT +IMSUB | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUB +IMSUM | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUM +IMTAN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMTAN +OCT2BIN | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOBIN +OCT2DEC | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTODEC +OCT2HEX | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOHEX ## CATEGORY_FINANCIAL -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ACCRINT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\AccruedInterest::periodic -ACCRINTM | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\AccruedInterest::atMaturity -AMORDEGRC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORDEGRC -AMORLINC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORLINC -COUPDAYBS | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYBS -COUPDAYS | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYS -COUPDAYSNC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYSNC -COUPNCD | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPNCD -COUPNUM | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPNUM -COUPPCD | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPPCD -CUMIPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Cumulative::interest -CUMPRINC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Cumulative::principal -DB | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::DB -DDB | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::DDB -DISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Rates::discount -DOLLARDE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::decimal -DOLLARFR | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::fractional -DURATION | **Not yet Implemented** -EFFECT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\InterestRate::effective -FV | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::futureValue -FVSCHEDULE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::futureValue -INTRATE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Rates::interest -IPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::payment -IRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::rate -ISPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::schedulePayment -MDURATION | **Not yet Implemented** -MIRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::modifiedRate -NOMINAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\InterestRate::nominal -NPER | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::periods -NPV | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::presentValue -ODDFPRICE | **Not yet Implemented** -ODDFYIELD | **Not yet Implemented** -ODDLPRICE | **Not yet Implemented** -ODDLYIELD | **Not yet Implemented** -PDURATION | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::periods -PMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Payments::annuity -PPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Payments::interestPayment -PRICE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::price -PRICEDISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::priceDiscounted -PRICEMAT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::priceAtMaturity -PV | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::presentValue -RATE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::rate -RECEIVED | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::received -RRI | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::interestRate -SLN | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::SLN -SYD | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::SYD -TBILLEQ | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::bondEquivalentYield -TBILLPRICE | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::price -TBILLYIELD | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::yield -USDOLLAR | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::format -VDB | **Not yet Implemented** -XIRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\NonPeriodic::rate -XNPV | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\NonPeriodic::presentValue -YIELD | **Not yet Implemented** -YIELDDISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Yields::yieldDiscounted -YIELDMAT | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Yields::yieldAtMaturity +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +ACCRINT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINT +ACCRINTM | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINTM +AMORDEGRC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORDEGRC +AMORLINC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORLINC +COUPDAYBS | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYBS +COUPDAYS | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYS +COUPDAYSNC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYSNC +COUPNCD | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNCD +COUPNUM | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNUM +COUPPCD | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPPCD +CUMIPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::CUMIPMT +CUMPRINC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::CUMPRINC +DB | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DB +DDB | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DDB +DISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DISC +DOLLARDE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DOLLARDE +DOLLARFR | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DOLLARFR +DURATION | **Not yet Implemented** +EFFECT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::EFFECT +FV | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FV +FVSCHEDULE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FVSCHEDULE +INTRATE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::INTRATE +IPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::IPMT +IRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial::IRR +ISPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ISPMT +MDURATION | **Not yet Implemented** +MIRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial::MIRR +NOMINAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NOMINAL +NPER | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPER +NPV | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPV +ODDFPRICE | **Not yet Implemented** +ODDFYIELD | **Not yet Implemented** +ODDLPRICE | **Not yet Implemented** +ODDLYIELD | **Not yet Implemented** +PDURATION | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PDURATION +PMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PMT +PPMT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PPMT +PRICE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICE +PRICEDISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICEDISC +PRICEMAT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICEMAT +PV | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PV +RATE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RATE +RECEIVED | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RECEIVED +RRI | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RRI +SLN | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SLN +SYD | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SYD +TBILLEQ | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLEQ +TBILLPRICE | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLPRICE +TBILLYIELD | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLYIELD +USDOLLAR | **Not yet Implemented** +VDB | **Not yet Implemented** +XIRR | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XIRR +XNPV | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XNPV +YIELD | **Not yet Implemented** +YIELDDISC | \PhpOffice\PhpSpreadsheet\Calculation\Financial::YIELDDISC +YIELDMAT | \PhpOffice\PhpSpreadsheet\Calculation\Financial::YIELDMAT ## CATEGORY_INFORMATION -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -CELL | **Not yet Implemented** -ERROR.TYPE | \PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError::type -INFO | **Not yet Implemented** -ISBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isBlank -ISERR | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isErr -ISERROR | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isError -ISEVEN | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isEven -ISFORMULA | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isFormula -ISLOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isLogical -ISNA | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isNa -ISNONTEXT | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isNonText -ISNUMBER | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isNumber -ISODD | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isOdd -ISOMITTED | **Not yet Implemented** -ISREF | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isRef -ISTEXT | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isText -N | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::asNumber -NA | \PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError::NA -SHEET | **Not yet Implemented** -SHEETS | **Not yet Implemented** -TYPE | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::type +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +CELL | **Not yet Implemented** +ERROR.TYPE | \PhpOffice\PhpSpreadsheet\Calculation\Functions::ERROR_TYPE +INFO | **Not yet Implemented** +ISBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_BLANK +ISERR | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ERR +ISERROR | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ERROR +ISEVEN | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_EVEN +ISFORMULA | \PhpOffice\PhpSpreadsheet\Calculation\Functions::ISFORMULA +ISLOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_LOGICAL +ISNA | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NA +ISNONTEXT | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NONTEXT +ISNUMBER | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NUMBER +ISODD | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ODD +ISREF | **Not yet Implemented** +ISTEXT | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_TEXT +N | \PhpOffice\PhpSpreadsheet\Calculation\Functions::N +NA | \PhpOffice\PhpSpreadsheet\Calculation\Functions::NA +TYPE | \PhpOffice\PhpSpreadsheet\Calculation\Functions::TYPE ## CATEGORY_LOGICAL -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -AND | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalAnd -BYCOL | **Not yet Implemented** -BYROW | **Not yet Implemented** -FALSE | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean::FALSE -IF | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::statementIf -IFERROR | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFERROR -IFNA | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFNA -IFS | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFS -LAMBDA | **Not yet Implemented** -LET | **Not yet Implemented** -MAKEARRAY | **Not yet Implemented** -MAP | **Not yet Implemented** -NOT | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::NOT -OR | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalOr -REDUCE | **Not yet Implemented** -SCAN | **Not yet Implemented** -SWITCH | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::statementSwitch -TRUE | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean::TRUE -XOR | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalXor +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +AND | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalAnd +FALSE | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE +IF | \PhpOffice\PhpSpreadsheet\Calculation\Logical::STATEMENT_IF +IFERROR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR +NOT | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT +OR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalOr +TRUE | \PhpOffice\PhpSpreadsheet\Calculation\Logical::TRUE +XOR | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalXor ## CATEGORY_LOOKUP_AND_REFERENCE -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ADDRESS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Address::cell -AREAS | **Not yet Implemented** -CHOOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Selection::CHOOSE -CHOOSECOLS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::chooseCols -CHOOSEROWS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::chooseRows -COLUMN | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::COLUMN -COLUMNS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::COLUMNS -DROP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::drop -EXPAND | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::expand -FILTER | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Filter::filter -FORMULATEXT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Formula::text -GETPIVOTDATA | **Not yet Implemented** -GROUPBY | **Not yet Implemented** -HLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\HLookup::lookup -HSTACK | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Hstack::hstack -HYPERLINK | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Hyperlink::set -INDEX | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix::index -INDIRECT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Indirect::INDIRECT -LOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Lookup::lookup -MATCH | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ExcelMatch::MATCH -OFFSET | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Offset::OFFSET -ROW | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::ROW -ROWS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::ROWS -RTD | **Not yet Implemented** -SORT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Sort::sort -SORTBY | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Sort::sortBy -TAKE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::take -TOCOL | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\TorowTocol::tocol -TOROW | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\TorowTocol::torow -TRANSPOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix::transpose -UNIQUE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Unique::unique -VLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\VLookup::lookup -VSTACK | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Vstack::vstack -XLOOKUP | **Not yet Implemented** -XMATCH | **Not yet Implemented** +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +ADDRESS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CELL_ADDRESS +AREAS | **Not yet Implemented** +CHOOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE +COLUMN | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN +COLUMNS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS +FORMULATEXT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT +GETPIVOTDATA | **Not yet Implemented** +HLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HLOOKUP +HYPERLINK | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HYPERLINK +INDEX | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDEX +INDIRECT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDIRECT +LOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::LOOKUP +MATCH | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::MATCH +OFFSET | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::OFFSET +ROW | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROW +ROWS | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROWS +RTD | **Not yet Implemented** +TRANSPOSE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE +VLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP ## CATEGORY_MATH_AND_TRIG -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ABS | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Absolute::evaluate -ACOS | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::acos -ACOSH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::acosh -ACOT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::acot -ACOTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::acoth -AGGREGATE | **Not yet Implemented** -ARABIC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Arabic::evaluate -ASIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::asin -ASINH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::asinh -ATAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atan -ATAN2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atan2 -ATANH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atanh -BASE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Base::evaluate -CEILING | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::ceiling -CEILING.MATH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::math -CEILING.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::precise -COMBIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Combinations::withoutRepetition -COMBINA | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Combinations::withRepetition -COS | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::cos -COSH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::cosh -COT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::cot -COTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::coth -CSC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosecant::csc -CSCH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosecant::csch -DECIMAL | **Not yet Implemented** -DEGREES | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Angle::toDegrees -ECMA.CEILING | **Not yet Implemented** -EVEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::even -EXP | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp::evaluate -FACT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::fact -FACTDOUBLE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::factDouble -FLOOR | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::floor -FLOOR.MATH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::math -FLOOR.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::precise -GCD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Gcd::evaluate -INT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\IntClass::evaluate -ISO.CEILING | **Not yet Implemented** -LCM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Lcm::evaluate -LN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::natural -LOG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::withBase -LOG10 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::base10 -MDETERM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::determinant -MINVERSE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::inverse -MMULT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::multiply -MOD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::mod -MROUND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::multiple -MULTINOMIAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::multinomial -MUNIT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::identity -ODD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::odd -PI | pi -POWER | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::power -PRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::product -QUOTIENT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::quotient -RADIANS | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Angle::toRadians -RAND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::rand -RANDARRAY | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::randArray -RANDBETWEEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::randBetween -ROMAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Roman::evaluate -ROUND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::round -ROUNDBAHTDOWN | **Not yet Implemented** -ROUNDBAHTUP | **Not yet Implemented** -ROUNDDOWN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::down -ROUNDUP | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::up -SEC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Secant::sec -SECH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Secant::sech -SEQUENCE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::sequence -SERIESSUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SeriesSum::evaluate -SIGN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sign::evaluate -SIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sin -SINH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sinh -SQRT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sqrt::sqrt -SQRTPI | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sqrt::pi -SUBTOTAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Subtotal::evaluate -SUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sum::sumErroringStrings -SUMIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::SUMIF -SUMIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::SUMIFS -SUMPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sum::product -SUMSQ | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumSquare -SUMX2MY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXSquaredMinusYSquared -SUMX2PY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXSquaredPlusYSquared -SUMXMY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXMinusYSquared -TAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::tan -TANH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::tanh -TRUNC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trunc::evaluate -WRAPCOLS | **Not yet Implemented** -WRAPROWS | **Not yet Implemented** +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +ABS | abs +ACOS | acos +ACOSH | acosh +ACOT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT +ACOTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH +ASIN | asin +ASINH | asinh +ATAN | atan +ATAN2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::REVERSE_ATAN2 +ATANH | atanh +CEILING | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING +COMBIN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN +COS | cos +COSH | cosh +COT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COT +COTH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COTH +CSC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC +CSCH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH +DEGREES | rad2deg +EVEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN +EXP | exp +FACT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACT +FACTDOUBLE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACTDOUBLE +FLOOR | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FLOOR +GCD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD +INT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::INT +LCM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM +LN | log +LOG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LOG_BASE +LOG10 | log10 +MDETERM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MDETERM +MINVERSE | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MINVERSE +MMULT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MMULT +MOD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD +MROUND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND +MULTINOMIAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL +ODD | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ODD +PI | pi +POWER | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER +PRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::PRODUCT +QUOTIENT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT +RADIANS | deg2rad +RAND | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND +RANDBETWEEN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND +ROMAN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROMAN +ROUND | round +ROUNDDOWN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROUNDDOWN +ROUNDUP | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROUNDUP +SEC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SEC +SECH | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SECH +SERIESSUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SERIESSUM +SIGN | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SIGN +SIN | sin +SINH | sinh +SQRT | sqrt +SQRTPI | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SQRTPI +SUBTOTAL | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUBTOTAL +SUM | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUM +SUMIF | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMIF +SUMIFS | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMIFS +SUMPRODUCT | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMPRODUCT +SUMSQ | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMSQ +SUMX2MY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMX2MY2 +SUMX2PY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMX2PY2 +SUMXMY2 | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMXMY2 +TAN | tan +TANH | tanh +TRUNC | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::TRUNC ## CATEGORY_STATISTICAL -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -AVEDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::averageDeviations -AVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::average -AVERAGEA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::averageA -AVERAGEIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::AVERAGEIF -AVERAGEIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::AVERAGEIFS -BETA.DIST | **Not yet Implemented** -BETA.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::inverse -BETADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::distribution -BETAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::inverse -BINOM.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::distribution -BINOM.DIST.RANGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::range -BINOM.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::inverse -BINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::distribution -CHIDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionRightTail -CHIINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionLeftTail -CHISQ.DIST.RT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionRightTail -CHISQ.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseLeftTail -CHISQ.INV.RT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.TEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::test -CHITEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::test -CONFIDENCE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Confidence::CONFIDENCE -CONFIDENCE.NORM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Confidence::CONFIDENCE -CONFIDENCE.T | **Not yet Implemented** -CORREL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::CORREL -COUNT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNT -COUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNTA -COUNTBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNTBLANK -COUNTIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::COUNTIF -COUNTIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::COUNTIFS -COVAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::COVAR -COVARIANCE.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::COVAR -COVARIANCE.S | **Not yet Implemented** -CRITBINOM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::inverse -DEVSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::sumSquares -EXPON.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Exponential::distribution -EXPONDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Exponential::distribution -F.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\F::distribution -F.DIST.RT | **Not yet Implemented** -F.INV | **Not yet Implemented** -F.INV.RT | **Not yet Implemented** -F.TEST | **Not yet Implemented** -FDIST | **Not yet Implemented** -FINV | **Not yet Implemented** -FISHER | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Fisher::distribution -FISHERINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Fisher::inverse -FORECAST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::FORECAST -FORECAST.ETS | **Not yet Implemented** -FORECAST.ETS.CONFINT | **Not yet Implemented** -FORECAST.ETS.SEASONALITY | **Not yet Implemented** -FORECAST.ETS.STAT | **Not yet Implemented** -FORECAST.LINEAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::FORECAST -FREQUENCY | **Not yet Implemented** -FTEST | **Not yet Implemented** -GAMMA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::gamma -GAMMA.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::distribution -GAMMA.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::inverse -GAMMADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::distribution -GAMMAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::inverse -GAMMALN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::ln -GAMMALN.PRECISE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::ln -GAUSS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::gauss -GEOMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::geometric -GROWTH | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::GROWTH -HARMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::harmonic -HYPGEOM.DIST | **Not yet Implemented** -HYPGEOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\HyperGeometric::distribution -INTERCEPT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::INTERCEPT -KURT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::kurtosis -LARGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Size::large -LINEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::LINEST -LOGEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::LOGEST -LOGINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::inverse -LOGNORM.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::distribution -LOGNORM.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::inverse -LOGNORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::cumulative -MAX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum::max -MAXA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum::maxA -MAXIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::MAXIFS -MEDIAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::median -MEDIANIF | **Not yet Implemented** -MIN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum::min -MINA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum::minA -MINIFS | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::MINIFS -MODE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::mode -MODE.MULT | **Not yet Implemented** -MODE.SNGL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::mode -NEGBINOM.DIST | **Not yet Implemented** -NEGBINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::negative -NORM.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::distribution -NORM.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::inverse -NORM.S.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::distribution -NORM.S.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::inverse -NORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::distribution -NORMINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::inverse -NORMSDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::cumulative -NORMSINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::inverse -PEARSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::CORREL -PERCENTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTILE -PERCENTILE.EXC | **Not yet Implemented** -PERCENTILE.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTILE -PERCENTRANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTRANK -PERCENTRANK.EXC | **Not yet Implemented** -PERCENTRANK.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTRANK -PERMUT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations::PERMUT -PERMUTATIONA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations::PERMUTATIONA -PHI | **Not yet Implemented** -POISSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Poisson::distribution -POISSON.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Poisson::distribution -PROB | **Not yet Implemented** -QUARTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::QUARTILE -QUARTILE.EXC | **Not yet Implemented** -QUARTILE.INC | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::QUARTILE -RANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::RANK -RANK.AVG | **Not yet Implemented** -RANK.EQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::RANK -RSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::RSQ -SKEW | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::skew -SKEW.P | **Not yet Implemented** -SLOPE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::SLOPE -SMALL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Size::small -STANDARDIZE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Standardize::execute -STDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEV -STDEV.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVP -STDEV.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEV -STDEVA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVA -STDEVP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVP -STDEVPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVPA -STEYX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::STEYX -T.DIST | **Not yet Implemented** -T.DIST.2T | **Not yet Implemented** -T.DIST.RT | **Not yet Implemented** -T.INV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::inverse -T.INV.2T | **Not yet Implemented** -T.TEST | **Not yet Implemented** -TDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::distribution -TINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::inverse -TREND | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::TREND -TRIMMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::trim -TTEST | **Not yet Implemented** -VAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VAR -VAR.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARP -VAR.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VAR -VARA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARA -VARP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARP -VARPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARPA -WEIBULL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Weibull::distribution -WEIBULL.DIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Weibull::distribution -Z.TEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::zTest -ZTEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::zTest +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +AVEDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVEDEV +AVERAGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGE +AVERAGEA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEA +AVERAGEIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEIF +AVERAGEIFS | **Not yet Implemented** +BETADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST +BETAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV +BINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST +CHIDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST +CHIINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV +CHITEST | **Not yet Implemented** +CONFIDENCE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE +CORREL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL +COUNT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNT +COUNTA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA +COUNTBLANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTBLANK +COUNTIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF +COUNTIFS | **Not yet Implemented** +COVAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR +CRITBINOM | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM +DEVSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ +EXPONDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST +FDIST | **Not yet Implemented** +FINV | **Not yet Implemented** +FISHER | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER +FISHERINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHERINV +FORECAST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FORECAST +FREQUENCY | **Not yet Implemented** +FTEST | **Not yet Implemented** +GAMMADIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST +GAMMAINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV +GAMMALN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN +GEOMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN +GROWTH | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GROWTH +HARMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN +HYPGEOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HYPGEOMDIST +INTERCEPT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::INTERCEPT +KURT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::KURT +LARGE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LARGE +LINEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LINEST +LOGEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST +LOGINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV +LOGNORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST +MAX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX +MAXA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA +MAXIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIF +MEDIAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MEDIAN +MEDIANIF | **Not yet Implemented** +MIN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MIN +MINA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA +MINIF | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIF +MODE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE +MODE.SNGL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE +NEGBINOMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST +NORMDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST +NORMINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV +NORMSDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST +NORMSINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV +PEARSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL +PERCENTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE +PERCENTRANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK +PERMUT | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT +POISSON | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON +PROB | **Not yet Implemented** +QUARTILE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE +RANK | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK +RSQ | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RSQ +SKEW | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW +SLOPE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE +SMALL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL +STANDARDIZE | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE +STDEV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV +STDEV.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV +STDEV.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP +STDEVA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVA +STDEVP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP +STDEVPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA +STEYX | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX +TDIST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST +TINV | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV +TREND | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND +TRIMMEAN | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TRIMMEAN +TTEST | **Not yet Implemented** +VAR | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc +VAR.P | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP +VAR.S | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc +VARA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARA +VARP | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP +VARPA | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA +WEIBULL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL +ZTEST | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST ## CATEGORY_TEXT_AND_DATA -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ARRAYTOTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::fromArray -ASC | **Not yet Implemented** -BAHTTEXT | **Not yet Implemented** -CHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character -CLEAN | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::nonPrintable -CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code -CONCAT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::CONCATENATE -CONCATENATE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::actualCONCATENATE -DBCS | **Not yet Implemented** -DOLLAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::DOLLAR -EXACT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::exact -FIND | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::sensitive -FINDB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::sensitive -FIXED | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::FIXEDFORMAT -ISTHAIDIGIT | **Not yet Implemented** -JIS | **Not yet Implemented** -LEFT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::left -LEFTB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::left -LEN | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::length -LENB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::length -LOWER | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::lower -MID | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::mid -MIDB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::mid -NUMBERSTRING | **Not yet Implemented** -NUMBERVALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::NUMBERVALUE -PHONETIC | **Not yet Implemented** -PROPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::proper -REPLACE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::replace -REPLACEB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::replace -REPT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::builtinREPT -RIGHT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::right -RIGHTB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::right -SEARCH | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::insensitive -SEARCHB | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::insensitive -SUBSTITUTE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::substitute -T | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::test -TEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::TEXTFORMAT -TEXTAFTER | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::after -TEXTBEFORE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::before -TEXTJOIN | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::TEXTJOIN -TEXTSPLIT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::split -THAIDIGIT | **Not yet Implemented** -THAINUMSOUND | **Not yet Implemented** -THAINUMSTRING | **Not yet Implemented** -THAISTRINGLENGTH | **Not yet Implemented** -TRIM | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::spaces -UNICHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character -UNICODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code -UPPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::upper -VALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::VALUE -VALUETOTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::valueToText - -## CATEGORY_WEB - -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ENCODEURL | \PhpOffice\PhpSpreadsheet\Calculation\Web\Service::urlEncode -FILTERXML | **Not yet Implemented** -WEBSERVICE | \PhpOffice\PhpSpreadsheet\Calculation\Web\Service::webService - -## CATEGORY_UNCATEGORISED - -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- - -## CATEGORY_MICROSOFT_INTERNAL - -Excel Function | PhpSpreadsheet Function --------------------------|-------------------------------------- -ANCHORARRAY | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::anchorArray -SINGLE | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::single +Excel Function | PhpSpreadsheet Function +--------------------|------------------------------------------- +ASC | **Not yet Implemented** +BAHTTEXT | **Not yet Implemented** +CHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER +CLEAN | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMNONPRINTABLE +CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE +CONCAT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE +CONCATENATE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE +DOLLAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::DOLLAR +EXACT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT +FIND | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE +FINDB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE +FIXED | \PhpOffice\PhpSpreadsheet\Calculation\TextData::FIXEDFORMAT +JIS | **Not yet Implemented** +LEFT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT +LEFTB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT +LEN | \PhpOffice\PhpSpreadsheet\Calculation\TextData::STRINGLENGTH +LENB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::STRINGLENGTH +LOWER | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LOWERCASE +MID | \PhpOffice\PhpSpreadsheet\Calculation\TextData::MID +MIDB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::MID +NUMBERVALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::NUMBERVALUE +PHONETIC | **Not yet Implemented** +PROPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData::PROPERCASE +REPLACE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE +REPLACEB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE +REPT | str_repeat +RIGHT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RIGHT +RIGHTB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RIGHT +SEARCH | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE +SEARCHB | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE +SUBSTITUTE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SUBSTITUTE +T | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RETURNSTRING +TEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTFORMAT +TEXTJOIN | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTJOIN +TRIM | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMSPACES +UNICHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER +UNICODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE +UPPER | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE +VALUE | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE diff --git a/docs/references/function-list-by-name-compact.md b/docs/references/function-list-by-name-compact.md deleted file mode 100644 index 4df84d2935..0000000000 --- a/docs/references/function-list-by-name-compact.md +++ /dev/null @@ -1,663 +0,0 @@ -# Function list by name compact - -Category should be prefixed by `CATEGORY_` to match the values in \PhpOffice\PhpSpreadsheet\Calculation\Category - -Function should be prefixed by `PhpOffice\PhpSpreadsheet\Calculation\` - -A less compact list can be found [here](./function-list-by-name.md) - - -## A - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -ABS | MATH_AND_TRIG | MathTrig\Absolute::evaluate -ACCRINT | FINANCIAL | Financial\Securities\AccruedInterest::periodic -ACCRINTM | FINANCIAL | Financial\Securities\AccruedInterest::atMaturity -ACOS | MATH_AND_TRIG | MathTrig\Trig\Cosine::acos -ACOSH | MATH_AND_TRIG | MathTrig\Trig\Cosine::acosh -ACOT | MATH_AND_TRIG | MathTrig\Trig\Cotangent::acot -ACOTH | MATH_AND_TRIG | MathTrig\Trig\Cotangent::acoth -ADDRESS | LOOKUP_AND_REFERENCE | LookupRef\Address::cell -AGGREGATE | MATH_AND_TRIG | **Not yet Implemented** -AMORDEGRC | FINANCIAL | Financial\Amortization::AMORDEGRC -AMORLINC | FINANCIAL | Financial\Amortization::AMORLINC -ANCHORARRAY | MICROSOFT_INTERNAL | Internal\ExcelArrayPseudoFunctions::anchorArray -AND | LOGICAL | Logical\Operations::logicalAnd -ARABIC | MATH_AND_TRIG | MathTrig\Arabic::evaluate -AREAS | LOOKUP_AND_REFERENCE | **Not yet Implemented** -ARRAYTOTEXT | TEXT_AND_DATA | TextData\Text::fromArray -ASC | TEXT_AND_DATA | **Not yet Implemented** -ASIN | MATH_AND_TRIG | MathTrig\Trig\Sine::asin -ASINH | MATH_AND_TRIG | MathTrig\Trig\Sine::asinh -ATAN | MATH_AND_TRIG | MathTrig\Trig\Tangent::atan -ATAN2 | MATH_AND_TRIG | MathTrig\Trig\Tangent::atan2 -ATANH | MATH_AND_TRIG | MathTrig\Trig\Tangent::atanh -AVEDEV | STATISTICAL | Statistical\Averages::averageDeviations -AVERAGE | STATISTICAL | Statistical\Averages::average -AVERAGEA | STATISTICAL | Statistical\Averages::averageA -AVERAGEIF | STATISTICAL | Statistical\Conditional::AVERAGEIF -AVERAGEIFS | STATISTICAL | Statistical\Conditional::AVERAGEIFS - -## B - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -BAHTTEXT | TEXT_AND_DATA | **Not yet Implemented** -BASE | MATH_AND_TRIG | MathTrig\Base::evaluate -BESSELI | ENGINEERING | Engineering\BesselI::BESSELI -BESSELJ | ENGINEERING | Engineering\BesselJ::BESSELJ -BESSELK | ENGINEERING | Engineering\BesselK::BESSELK -BESSELY | ENGINEERING | Engineering\BesselY::BESSELY -BETA.DIST | STATISTICAL | **Not yet Implemented** -BETA.INV | STATISTICAL | Statistical\Distributions\Beta::inverse -BETADIST | STATISTICAL | Statistical\Distributions\Beta::distribution -BETAINV | STATISTICAL | Statistical\Distributions\Beta::inverse -BIN2DEC | ENGINEERING | Engineering\ConvertBinary::toDecimal -BIN2HEX | ENGINEERING | Engineering\ConvertBinary::toHex -BIN2OCT | ENGINEERING | Engineering\ConvertBinary::toOctal -BINOM.DIST | STATISTICAL | Statistical\Distributions\Binomial::distribution -BINOM.DIST.RANGE | STATISTICAL | Statistical\Distributions\Binomial::range -BINOM.INV | STATISTICAL | Statistical\Distributions\Binomial::inverse -BINOMDIST | STATISTICAL | Statistical\Distributions\Binomial::distribution -BITAND | ENGINEERING | Engineering\BitWise::BITAND -BITLSHIFT | ENGINEERING | Engineering\BitWise::BITLSHIFT -BITOR | ENGINEERING | Engineering\BitWise::BITOR -BITRSHIFT | ENGINEERING | Engineering\BitWise::BITRSHIFT -BITXOR | ENGINEERING | Engineering\BitWise::BITXOR -BYCOL | LOGICAL | **Not yet Implemented** -BYROW | LOGICAL | **Not yet Implemented** - -## C - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -CEILING | MATH_AND_TRIG | MathTrig\Ceiling::ceiling -CEILING.MATH | MATH_AND_TRIG | MathTrig\Ceiling::math -CEILING.PRECISE | MATH_AND_TRIG | MathTrig\Ceiling::precise -CELL | INFORMATION | **Not yet Implemented** -CHAR | TEXT_AND_DATA | TextData\CharacterConvert::character -CHIDIST | STATISTICAL | Statistical\Distributions\ChiSquared::distributionRightTail -CHIINV | STATISTICAL | Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.DIST | STATISTICAL | Statistical\Distributions\ChiSquared::distributionLeftTail -CHISQ.DIST.RT | STATISTICAL | Statistical\Distributions\ChiSquared::distributionRightTail -CHISQ.INV | STATISTICAL | Statistical\Distributions\ChiSquared::inverseLeftTail -CHISQ.INV.RT | STATISTICAL | Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.TEST | STATISTICAL | Statistical\Distributions\ChiSquared::test -CHITEST | STATISTICAL | Statistical\Distributions\ChiSquared::test -CHOOSE | LOOKUP_AND_REFERENCE | LookupRef\Selection::CHOOSE -CHOOSECOLS | LOOKUP_AND_REFERENCE | LookupRef\ChooseRowsEtc::chooseCols -CHOOSEROWS | LOOKUP_AND_REFERENCE | LookupRef\ChooseRowsEtc::chooseRows -CLEAN | TEXT_AND_DATA | TextData\Trim::nonPrintable -CODE | TEXT_AND_DATA | TextData\CharacterConvert::code -COLUMN | LOOKUP_AND_REFERENCE | LookupRef\RowColumnInformation::COLUMN -COLUMNS | LOOKUP_AND_REFERENCE | LookupRef\RowColumnInformation::COLUMNS -COMBIN | MATH_AND_TRIG | MathTrig\Combinations::withoutRepetition -COMBINA | MATH_AND_TRIG | MathTrig\Combinations::withRepetition -COMPLEX | ENGINEERING | Engineering\Complex::COMPLEX -CONCAT | TEXT_AND_DATA | TextData\Concatenate::CONCATENATE -CONCATENATE | TEXT_AND_DATA | TextData\Concatenate::actualCONCATENATE -CONFIDENCE | STATISTICAL | Statistical\Confidence::CONFIDENCE -CONFIDENCE.NORM | STATISTICAL | Statistical\Confidence::CONFIDENCE -CONFIDENCE.T | STATISTICAL | **Not yet Implemented** -CONVERT | ENGINEERING | Engineering\ConvertUOM::CONVERT -CORREL | STATISTICAL | Statistical\Trends::CORREL -COS | MATH_AND_TRIG | MathTrig\Trig\Cosine::cos -COSH | MATH_AND_TRIG | MathTrig\Trig\Cosine::cosh -COT | MATH_AND_TRIG | MathTrig\Trig\Cotangent::cot -COTH | MATH_AND_TRIG | MathTrig\Trig\Cotangent::coth -COUNT | STATISTICAL | Statistical\Counts::COUNT -COUNTA | STATISTICAL | Statistical\Counts::COUNTA -COUNTBLANK | STATISTICAL | Statistical\Counts::COUNTBLANK -COUNTIF | STATISTICAL | Statistical\Conditional::COUNTIF -COUNTIFS | STATISTICAL | Statistical\Conditional::COUNTIFS -COUPDAYBS | FINANCIAL | Financial\Coupons::COUPDAYBS -COUPDAYS | FINANCIAL | Financial\Coupons::COUPDAYS -COUPDAYSNC | FINANCIAL | Financial\Coupons::COUPDAYSNC -COUPNCD | FINANCIAL | Financial\Coupons::COUPNCD -COUPNUM | FINANCIAL | Financial\Coupons::COUPNUM -COUPPCD | FINANCIAL | Financial\Coupons::COUPPCD -COVAR | STATISTICAL | Statistical\Trends::COVAR -COVARIANCE.P | STATISTICAL | Statistical\Trends::COVAR -COVARIANCE.S | STATISTICAL | **Not yet Implemented** -CRITBINOM | STATISTICAL | Statistical\Distributions\Binomial::inverse -CSC | MATH_AND_TRIG | MathTrig\Trig\Cosecant::csc -CSCH | MATH_AND_TRIG | MathTrig\Trig\Cosecant::csch -CUBEKPIMEMBER | CUBE | **Not yet Implemented** -CUBEMEMBER | CUBE | **Not yet Implemented** -CUBEMEMBERPROPERTY | CUBE | **Not yet Implemented** -CUBERANKEDMEMBER | CUBE | **Not yet Implemented** -CUBESET | CUBE | **Not yet Implemented** -CUBESETCOUNT | CUBE | **Not yet Implemented** -CUBEVALUE | CUBE | **Not yet Implemented** -CUMIPMT | FINANCIAL | Financial\CashFlow\Constant\Periodic\Cumulative::interest -CUMPRINC | FINANCIAL | Financial\CashFlow\Constant\Periodic\Cumulative::principal - -## D - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -DATE | DATE_AND_TIME | DateTimeExcel\Date::fromYMD -DATEDIF | DATE_AND_TIME | DateTimeExcel\Difference::interval -DATESTRING | DATE_AND_TIME | **Not yet Implemented** -DATEVALUE | DATE_AND_TIME | DateTimeExcel\DateValue::fromString -DAVERAGE | DATABASE | Database\DAverage::evaluate -DAY | DATE_AND_TIME | DateTimeExcel\DateParts::day -DAYS | DATE_AND_TIME | DateTimeExcel\Days::between -DAYS360 | DATE_AND_TIME | DateTimeExcel\Days360::between -DB | FINANCIAL | Financial\Depreciation::DB -DBCS | TEXT_AND_DATA | **Not yet Implemented** -DCOUNT | DATABASE | Database\DCount::evaluate -DCOUNTA | DATABASE | Database\DCountA::evaluate -DDB | FINANCIAL | Financial\Depreciation::DDB -DEC2BIN | ENGINEERING | Engineering\ConvertDecimal::toBinary -DEC2HEX | ENGINEERING | Engineering\ConvertDecimal::toHex -DEC2OCT | ENGINEERING | Engineering\ConvertDecimal::toOctal -DECIMAL | MATH_AND_TRIG | **Not yet Implemented** -DEGREES | MATH_AND_TRIG | MathTrig\Angle::toDegrees -DELTA | ENGINEERING | Engineering\Compare::DELTA -DEVSQ | STATISTICAL | Statistical\Deviations::sumSquares -DGET | DATABASE | Database\DGet::evaluate -DISC | FINANCIAL | Financial\Securities\Rates::discount -DMAX | DATABASE | Database\DMax::evaluate -DMIN | DATABASE | Database\DMin::evaluate -DOLLAR | TEXT_AND_DATA | TextData\Format::DOLLAR -DOLLARDE | FINANCIAL | Financial\Dollar::decimal -DOLLARFR | FINANCIAL | Financial\Dollar::fractional -DPRODUCT | DATABASE | Database\DProduct::evaluate -DROP | LOOKUP_AND_REFERENCE | LookupRef\ChooseRowsEtc::drop -DSTDEV | DATABASE | Database\DStDev::evaluate -DSTDEVP | DATABASE | Database\DStDevP::evaluate -DSUM | DATABASE | Database\DSum::evaluate -DURATION | FINANCIAL | **Not yet Implemented** -DVAR | DATABASE | Database\DVar::evaluate -DVARP | DATABASE | Database\DVarP::evaluate - -## E - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -ECMA.CEILING | MATH_AND_TRIG | **Not yet Implemented** -EDATE | DATE_AND_TIME | DateTimeExcel\Month::adjust -EFFECT | FINANCIAL | Financial\InterestRate::effective -ENCODEURL | WEB | Web\Service::urlEncode -EOMONTH | DATE_AND_TIME | DateTimeExcel\Month::lastDay -ERF | ENGINEERING | Engineering\Erf::ERF -ERF.PRECISE | ENGINEERING | Engineering\Erf::ERFPRECISE -ERFC | ENGINEERING | Engineering\ErfC::ERFC -ERFC.PRECISE | ENGINEERING | Engineering\ErfC::ERFC -ERROR.TYPE | INFORMATION | Information\ExcelError::type -EVEN | MATH_AND_TRIG | MathTrig\Round::even -EXACT | TEXT_AND_DATA | TextData\Text::exact -EXP | MATH_AND_TRIG | MathTrig\Exp::evaluate -EXPAND | LOOKUP_AND_REFERENCE | LookupRef\ChooseRowsEtc::expand -EXPON.DIST | STATISTICAL | Statistical\Distributions\Exponential::distribution -EXPONDIST | STATISTICAL | Statistical\Distributions\Exponential::distribution - -## F - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -F.DIST | STATISTICAL | Statistical\Distributions\F::distribution -F.DIST.RT | STATISTICAL | **Not yet Implemented** -F.INV | STATISTICAL | **Not yet Implemented** -F.INV.RT | STATISTICAL | **Not yet Implemented** -F.TEST | STATISTICAL | **Not yet Implemented** -FACT | MATH_AND_TRIG | MathTrig\Factorial::fact -FACTDOUBLE | MATH_AND_TRIG | MathTrig\Factorial::factDouble -FALSE | LOGICAL | Logical\Boolean::FALSE -FDIST | STATISTICAL | **Not yet Implemented** -FILTER | LOOKUP_AND_REFERENCE | LookupRef\Filter::filter -FILTERXML | WEB | **Not yet Implemented** -FIND | TEXT_AND_DATA | TextData\Search::sensitive -FINDB | TEXT_AND_DATA | TextData\Search::sensitive -FINV | STATISTICAL | **Not yet Implemented** -FISHER | STATISTICAL | Statistical\Distributions\Fisher::distribution -FISHERINV | STATISTICAL | Statistical\Distributions\Fisher::inverse -FIXED | TEXT_AND_DATA | TextData\Format::FIXEDFORMAT -FLOOR | MATH_AND_TRIG | MathTrig\Floor::floor -FLOOR.MATH | MATH_AND_TRIG | MathTrig\Floor::math -FLOOR.PRECISE | MATH_AND_TRIG | MathTrig\Floor::precise -FORECAST | STATISTICAL | Statistical\Trends::FORECAST -FORECAST.ETS | STATISTICAL | **Not yet Implemented** -FORECAST.ETS.CONFINT | STATISTICAL | **Not yet Implemented** -FORECAST.ETS.SEASONALITY | STATISTICAL | **Not yet Implemented** -FORECAST.ETS.STAT | STATISTICAL | **Not yet Implemented** -FORECAST.LINEAR | STATISTICAL | Statistical\Trends::FORECAST -FORMULATEXT | LOOKUP_AND_REFERENCE | LookupRef\Formula::text -FREQUENCY | STATISTICAL | **Not yet Implemented** -FTEST | STATISTICAL | **Not yet Implemented** -FV | FINANCIAL | Financial\CashFlow\Constant\Periodic::futureValue -FVSCHEDULE | FINANCIAL | Financial\CashFlow\Single::futureValue - -## G - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -GAMMA | STATISTICAL | Statistical\Distributions\Gamma::gamma -GAMMA.DIST | STATISTICAL | Statistical\Distributions\Gamma::distribution -GAMMA.INV | STATISTICAL | Statistical\Distributions\Gamma::inverse -GAMMADIST | STATISTICAL | Statistical\Distributions\Gamma::distribution -GAMMAINV | STATISTICAL | Statistical\Distributions\Gamma::inverse -GAMMALN | STATISTICAL | Statistical\Distributions\Gamma::ln -GAMMALN.PRECISE | STATISTICAL | Statistical\Distributions\Gamma::ln -GAUSS | STATISTICAL | Statistical\Distributions\StandardNormal::gauss -GCD | MATH_AND_TRIG | MathTrig\Gcd::evaluate -GEOMEAN | STATISTICAL | Statistical\Averages\Mean::geometric -GESTEP | ENGINEERING | Engineering\Compare::GESTEP -GETPIVOTDATA | LOOKUP_AND_REFERENCE | **Not yet Implemented** -GROUPBY | LOOKUP_AND_REFERENCE | **Not yet Implemented** -GROWTH | STATISTICAL | Statistical\Trends::GROWTH - -## H - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -HARMEAN | STATISTICAL | Statistical\Averages\Mean::harmonic -HEX2BIN | ENGINEERING | Engineering\ConvertHex::toBinary -HEX2DEC | ENGINEERING | Engineering\ConvertHex::toDecimal -HEX2OCT | ENGINEERING | Engineering\ConvertHex::toOctal -HLOOKUP | LOOKUP_AND_REFERENCE | LookupRef\HLookup::lookup -HOUR | DATE_AND_TIME | DateTimeExcel\TimeParts::hour -HSTACK | LOOKUP_AND_REFERENCE | LookupRef\Hstack::hstack -HYPERLINK | LOOKUP_AND_REFERENCE | LookupRef\Hyperlink::set -HYPGEOM.DIST | STATISTICAL | **Not yet Implemented** -HYPGEOMDIST | STATISTICAL | Statistical\Distributions\HyperGeometric::distribution - -## I - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -IF | LOGICAL | Logical\Conditional::statementIf -IFERROR | LOGICAL | Logical\Conditional::IFERROR -IFNA | LOGICAL | Logical\Conditional::IFNA -IFS | LOGICAL | Logical\Conditional::IFS -IMABS | ENGINEERING | Engineering\ComplexFunctions::IMABS -IMAGINARY | ENGINEERING | Engineering\Complex::IMAGINARY -IMARGUMENT | ENGINEERING | Engineering\ComplexFunctions::IMARGUMENT -IMCONJUGATE | ENGINEERING | Engineering\ComplexFunctions::IMCONJUGATE -IMCOS | ENGINEERING | Engineering\ComplexFunctions::IMCOS -IMCOSH | ENGINEERING | Engineering\ComplexFunctions::IMCOSH -IMCOT | ENGINEERING | Engineering\ComplexFunctions::IMCOT -IMCSC | ENGINEERING | Engineering\ComplexFunctions::IMCSC -IMCSCH | ENGINEERING | Engineering\ComplexFunctions::IMCSCH -IMDIV | ENGINEERING | Engineering\ComplexOperations::IMDIV -IMEXP | ENGINEERING | Engineering\ComplexFunctions::IMEXP -IMLN | ENGINEERING | Engineering\ComplexFunctions::IMLN -IMLOG10 | ENGINEERING | Engineering\ComplexFunctions::IMLOG10 -IMLOG2 | ENGINEERING | Engineering\ComplexFunctions::IMLOG2 -IMPOWER | ENGINEERING | Engineering\ComplexFunctions::IMPOWER -IMPRODUCT | ENGINEERING | Engineering\ComplexOperations::IMPRODUCT -IMREAL | ENGINEERING | Engineering\Complex::IMREAL -IMSEC | ENGINEERING | Engineering\ComplexFunctions::IMSEC -IMSECH | ENGINEERING | Engineering\ComplexFunctions::IMSECH -IMSIN | ENGINEERING | Engineering\ComplexFunctions::IMSIN -IMSINH | ENGINEERING | Engineering\ComplexFunctions::IMSINH -IMSQRT | ENGINEERING | Engineering\ComplexFunctions::IMSQRT -IMSUB | ENGINEERING | Engineering\ComplexOperations::IMSUB -IMSUM | ENGINEERING | Engineering\ComplexOperations::IMSUM -IMTAN | ENGINEERING | Engineering\ComplexFunctions::IMTAN -INDEX | LOOKUP_AND_REFERENCE | LookupRef\Matrix::index -INDIRECT | LOOKUP_AND_REFERENCE | LookupRef\Indirect::INDIRECT -INFO | INFORMATION | **Not yet Implemented** -INT | MATH_AND_TRIG | MathTrig\IntClass::evaluate -INTERCEPT | STATISTICAL | Statistical\Trends::INTERCEPT -INTRATE | FINANCIAL | Financial\Securities\Rates::interest -IPMT | FINANCIAL | Financial\CashFlow\Constant\Periodic\Interest::payment -IRR | FINANCIAL | Financial\CashFlow\Variable\Periodic::rate -ISBLANK | INFORMATION | Information\Value::isBlank -ISERR | INFORMATION | Information\ErrorValue::isErr -ISERROR | INFORMATION | Information\ErrorValue::isError -ISEVEN | INFORMATION | Information\Value::isEven -ISFORMULA | INFORMATION | Information\Value::isFormula -ISLOGICAL | INFORMATION | Information\Value::isLogical -ISNA | INFORMATION | Information\ErrorValue::isNa -ISNONTEXT | INFORMATION | Information\Value::isNonText -ISNUMBER | INFORMATION | Information\Value::isNumber -ISO.CEILING | MATH_AND_TRIG | **Not yet Implemented** -ISODD | INFORMATION | Information\Value::isOdd -ISOMITTED | INFORMATION | **Not yet Implemented** -ISOWEEKNUM | DATE_AND_TIME | DateTimeExcel\Week::isoWeekNumber -ISPMT | FINANCIAL | Financial\CashFlow\Constant\Periodic\Interest::schedulePayment -ISREF | INFORMATION | Information\Value::isRef -ISTEXT | INFORMATION | Information\Value::isText -ISTHAIDIGIT | TEXT_AND_DATA | **Not yet Implemented** - -## J - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -JIS | TEXT_AND_DATA | **Not yet Implemented** - -## K - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -KURT | STATISTICAL | Statistical\Deviations::kurtosis - -## L - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -LAMBDA | LOGICAL | **Not yet Implemented** -LARGE | STATISTICAL | Statistical\Size::large -LCM | MATH_AND_TRIG | MathTrig\Lcm::evaluate -LEFT | TEXT_AND_DATA | TextData\Extract::left -LEFTB | TEXT_AND_DATA | TextData\Extract::left -LEN | TEXT_AND_DATA | TextData\Text::length -LENB | TEXT_AND_DATA | TextData\Text::length -LET | LOGICAL | **Not yet Implemented** -LINEST | STATISTICAL | Statistical\Trends::LINEST -LN | MATH_AND_TRIG | MathTrig\Logarithms::natural -LOG | MATH_AND_TRIG | MathTrig\Logarithms::withBase -LOG10 | MATH_AND_TRIG | MathTrig\Logarithms::base10 -LOGEST | STATISTICAL | Statistical\Trends::LOGEST -LOGINV | STATISTICAL | Statistical\Distributions\LogNormal::inverse -LOGNORM.DIST | STATISTICAL | Statistical\Distributions\LogNormal::distribution -LOGNORM.INV | STATISTICAL | Statistical\Distributions\LogNormal::inverse -LOGNORMDIST | STATISTICAL | Statistical\Distributions\LogNormal::cumulative -LOOKUP | LOOKUP_AND_REFERENCE | LookupRef\Lookup::lookup -LOWER | TEXT_AND_DATA | TextData\CaseConvert::lower - -## M - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -MAKEARRAY | LOGICAL | **Not yet Implemented** -MAP | LOGICAL | **Not yet Implemented** -MATCH | LOOKUP_AND_REFERENCE | LookupRef\ExcelMatch::MATCH -MAX | STATISTICAL | Statistical\Maximum::max -MAXA | STATISTICAL | Statistical\Maximum::maxA -MAXIFS | STATISTICAL | Statistical\Conditional::MAXIFS -MDETERM | MATH_AND_TRIG | MathTrig\MatrixFunctions::determinant -MDURATION | FINANCIAL | **Not yet Implemented** -MEDIAN | STATISTICAL | Statistical\Averages::median -MEDIANIF | STATISTICAL | **Not yet Implemented** -MID | TEXT_AND_DATA | TextData\Extract::mid -MIDB | TEXT_AND_DATA | TextData\Extract::mid -MIN | STATISTICAL | Statistical\Minimum::min -MINA | STATISTICAL | Statistical\Minimum::minA -MINIFS | STATISTICAL | Statistical\Conditional::MINIFS -MINUTE | DATE_AND_TIME | DateTimeExcel\TimeParts::minute -MINVERSE | MATH_AND_TRIG | MathTrig\MatrixFunctions::inverse -MIRR | FINANCIAL | Financial\CashFlow\Variable\Periodic::modifiedRate -MMULT | MATH_AND_TRIG | MathTrig\MatrixFunctions::multiply -MOD | MATH_AND_TRIG | MathTrig\Operations::mod -MODE | STATISTICAL | Statistical\Averages::mode -MODE.MULT | STATISTICAL | **Not yet Implemented** -MODE.SNGL | STATISTICAL | Statistical\Averages::mode -MONTH | DATE_AND_TIME | DateTimeExcel\DateParts::month -MROUND | MATH_AND_TRIG | MathTrig\Round::multiple -MULTINOMIAL | MATH_AND_TRIG | MathTrig\Factorial::multinomial -MUNIT | MATH_AND_TRIG | MathTrig\MatrixFunctions::identity - -## N - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -N | INFORMATION | Information\Value::asNumber -NA | INFORMATION | Information\ExcelError::NA -NEGBINOM.DIST | STATISTICAL | **Not yet Implemented** -NEGBINOMDIST | STATISTICAL | Statistical\Distributions\Binomial::negative -NETWORKDAYS | DATE_AND_TIME | DateTimeExcel\NetworkDays::count -NETWORKDAYS.INTL | DATE_AND_TIME | **Not yet Implemented** -NOMINAL | FINANCIAL | Financial\InterestRate::nominal -NORM.DIST | STATISTICAL | Statistical\Distributions\Normal::distribution -NORM.INV | STATISTICAL | Statistical\Distributions\Normal::inverse -NORM.S.DIST | STATISTICAL | Statistical\Distributions\StandardNormal::distribution -NORM.S.INV | STATISTICAL | Statistical\Distributions\StandardNormal::inverse -NORMDIST | STATISTICAL | Statistical\Distributions\Normal::distribution -NORMINV | STATISTICAL | Statistical\Distributions\Normal::inverse -NORMSDIST | STATISTICAL | Statistical\Distributions\StandardNormal::cumulative -NORMSINV | STATISTICAL | Statistical\Distributions\StandardNormal::inverse -NOT | LOGICAL | Logical\Operations::NOT -NOW | DATE_AND_TIME | DateTimeExcel\Current::now -NPER | FINANCIAL | Financial\CashFlow\Constant\Periodic::periods -NPV | FINANCIAL | Financial\CashFlow\Variable\Periodic::presentValue -NUMBERSTRING | TEXT_AND_DATA | **Not yet Implemented** -NUMBERVALUE | TEXT_AND_DATA | TextData\Format::NUMBERVALUE - -## O - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -OCT2BIN | ENGINEERING | Engineering\ConvertOctal::toBinary -OCT2DEC | ENGINEERING | Engineering\ConvertOctal::toDecimal -OCT2HEX | ENGINEERING | Engineering\ConvertOctal::toHex -ODD | MATH_AND_TRIG | MathTrig\Round::odd -ODDFPRICE | FINANCIAL | **Not yet Implemented** -ODDFYIELD | FINANCIAL | **Not yet Implemented** -ODDLPRICE | FINANCIAL | **Not yet Implemented** -ODDLYIELD | FINANCIAL | **Not yet Implemented** -OFFSET | LOOKUP_AND_REFERENCE | LookupRef\Offset::OFFSET -OR | LOGICAL | Logical\Operations::logicalOr - -## P - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -PDURATION | FINANCIAL | Financial\CashFlow\Single::periods -PEARSON | STATISTICAL | Statistical\Trends::CORREL -PERCENTILE | STATISTICAL | Statistical\Percentiles::PERCENTILE -PERCENTILE.EXC | STATISTICAL | **Not yet Implemented** -PERCENTILE.INC | STATISTICAL | Statistical\Percentiles::PERCENTILE -PERCENTRANK | STATISTICAL | Statistical\Percentiles::PERCENTRANK -PERCENTRANK.EXC | STATISTICAL | **Not yet Implemented** -PERCENTRANK.INC | STATISTICAL | Statistical\Percentiles::PERCENTRANK -PERMUT | STATISTICAL | Statistical\Permutations::PERMUT -PERMUTATIONA | STATISTICAL | Statistical\Permutations::PERMUTATIONA -PHI | STATISTICAL | **Not yet Implemented** -PHONETIC | TEXT_AND_DATA | **Not yet Implemented** -PI | MATH_AND_TRIG | pi -PMT | FINANCIAL | Financial\CashFlow\Constant\Periodic\Payments::annuity -POISSON | STATISTICAL | Statistical\Distributions\Poisson::distribution -POISSON.DIST | STATISTICAL | Statistical\Distributions\Poisson::distribution -POWER | MATH_AND_TRIG | MathTrig\Operations::power -PPMT | FINANCIAL | Financial\CashFlow\Constant\Periodic\Payments::interestPayment -PRICE | FINANCIAL | Financial\Securities\Price::price -PRICEDISC | FINANCIAL | Financial\Securities\Price::priceDiscounted -PRICEMAT | FINANCIAL | Financial\Securities\Price::priceAtMaturity -PROB | STATISTICAL | **Not yet Implemented** -PRODUCT | MATH_AND_TRIG | MathTrig\Operations::product -PROPER | TEXT_AND_DATA | TextData\CaseConvert::proper -PV | FINANCIAL | Financial\CashFlow\Constant\Periodic::presentValue - -## Q - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -QUARTILE | STATISTICAL | Statistical\Percentiles::QUARTILE -QUARTILE.EXC | STATISTICAL | **Not yet Implemented** -QUARTILE.INC | STATISTICAL | Statistical\Percentiles::QUARTILE -QUOTIENT | MATH_AND_TRIG | MathTrig\Operations::quotient - -## R - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -RADIANS | MATH_AND_TRIG | MathTrig\Angle::toRadians -RAND | MATH_AND_TRIG | MathTrig\Random::rand -RANDARRAY | MATH_AND_TRIG | MathTrig\Random::randArray -RANDBETWEEN | MATH_AND_TRIG | MathTrig\Random::randBetween -RANK | STATISTICAL | Statistical\Percentiles::RANK -RANK.AVG | STATISTICAL | **Not yet Implemented** -RANK.EQ | STATISTICAL | Statistical\Percentiles::RANK -RATE | FINANCIAL | Financial\CashFlow\Constant\Periodic\Interest::rate -RECEIVED | FINANCIAL | Financial\Securities\Price::received -REDUCE | LOGICAL | **Not yet Implemented** -REPLACE | TEXT_AND_DATA | TextData\Replace::replace -REPLACEB | TEXT_AND_DATA | TextData\Replace::replace -REPT | TEXT_AND_DATA | TextData\Concatenate::builtinREPT -RIGHT | TEXT_AND_DATA | TextData\Extract::right -RIGHTB | TEXT_AND_DATA | TextData\Extract::right -ROMAN | MATH_AND_TRIG | MathTrig\Roman::evaluate -ROUND | MATH_AND_TRIG | MathTrig\Round::round -ROUNDBAHTDOWN | MATH_AND_TRIG | **Not yet Implemented** -ROUNDBAHTUP | MATH_AND_TRIG | **Not yet Implemented** -ROUNDDOWN | MATH_AND_TRIG | MathTrig\Round::down -ROUNDUP | MATH_AND_TRIG | MathTrig\Round::up -ROW | LOOKUP_AND_REFERENCE | LookupRef\RowColumnInformation::ROW -ROWS | LOOKUP_AND_REFERENCE | LookupRef\RowColumnInformation::ROWS -RRI | FINANCIAL | Financial\CashFlow\Single::interestRate -RSQ | STATISTICAL | Statistical\Trends::RSQ -RTD | LOOKUP_AND_REFERENCE | **Not yet Implemented** - -## S - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -SCAN | LOGICAL | **Not yet Implemented** -SEARCH | TEXT_AND_DATA | TextData\Search::insensitive -SEARCHB | TEXT_AND_DATA | TextData\Search::insensitive -SEC | MATH_AND_TRIG | MathTrig\Trig\Secant::sec -SECH | MATH_AND_TRIG | MathTrig\Trig\Secant::sech -SECOND | DATE_AND_TIME | DateTimeExcel\TimeParts::second -SEQUENCE | MATH_AND_TRIG | MathTrig\MatrixFunctions::sequence -SERIESSUM | MATH_AND_TRIG | MathTrig\SeriesSum::evaluate -SHEET | INFORMATION | **Not yet Implemented** -SHEETS | INFORMATION | **Not yet Implemented** -SIGN | MATH_AND_TRIG | MathTrig\Sign::evaluate -SIN | MATH_AND_TRIG | MathTrig\Trig\Sine::sin -SINGLE | MICROSOFT_INTERNAL | Internal\ExcelArrayPseudoFunctions::single -SINH | MATH_AND_TRIG | MathTrig\Trig\Sine::sinh -SKEW | STATISTICAL | Statistical\Deviations::skew -SKEW.P | STATISTICAL | **Not yet Implemented** -SLN | FINANCIAL | Financial\Depreciation::SLN -SLOPE | STATISTICAL | Statistical\Trends::SLOPE -SMALL | STATISTICAL | Statistical\Size::small -SORT | LOOKUP_AND_REFERENCE | LookupRef\Sort::sort -SORTBY | LOOKUP_AND_REFERENCE | LookupRef\Sort::sortBy -SQRT | MATH_AND_TRIG | MathTrig\Sqrt::sqrt -SQRTPI | MATH_AND_TRIG | MathTrig\Sqrt::pi -STANDARDIZE | STATISTICAL | Statistical\Standardize::execute -STDEV | STATISTICAL | Statistical\StandardDeviations::STDEV -STDEV.P | STATISTICAL | Statistical\StandardDeviations::STDEVP -STDEV.S | STATISTICAL | Statistical\StandardDeviations::STDEV -STDEVA | STATISTICAL | Statistical\StandardDeviations::STDEVA -STDEVP | STATISTICAL | Statistical\StandardDeviations::STDEVP -STDEVPA | STATISTICAL | Statistical\StandardDeviations::STDEVPA -STEYX | STATISTICAL | Statistical\Trends::STEYX -SUBSTITUTE | TEXT_AND_DATA | TextData\Replace::substitute -SUBTOTAL | MATH_AND_TRIG | MathTrig\Subtotal::evaluate -SUM | MATH_AND_TRIG | MathTrig\Sum::sumErroringStrings -SUMIF | MATH_AND_TRIG | Statistical\Conditional::SUMIF -SUMIFS | MATH_AND_TRIG | Statistical\Conditional::SUMIFS -SUMPRODUCT | MATH_AND_TRIG | MathTrig\Sum::product -SUMSQ | MATH_AND_TRIG | MathTrig\SumSquares::sumSquare -SUMX2MY2 | MATH_AND_TRIG | MathTrig\SumSquares::sumXSquaredMinusYSquared -SUMX2PY2 | MATH_AND_TRIG | MathTrig\SumSquares::sumXSquaredPlusYSquared -SUMXMY2 | MATH_AND_TRIG | MathTrig\SumSquares::sumXMinusYSquared -SWITCH | LOGICAL | Logical\Conditional::statementSwitch -SYD | FINANCIAL | Financial\Depreciation::SYD - -## T - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -T | TEXT_AND_DATA | TextData\Text::test -T.DIST | STATISTICAL | **Not yet Implemented** -T.DIST.2T | STATISTICAL | **Not yet Implemented** -T.DIST.RT | STATISTICAL | **Not yet Implemented** -T.INV | STATISTICAL | Statistical\Distributions\StudentT::inverse -T.INV.2T | STATISTICAL | **Not yet Implemented** -T.TEST | STATISTICAL | **Not yet Implemented** -TAKE | LOOKUP_AND_REFERENCE | LookupRef\ChooseRowsEtc::take -TAN | MATH_AND_TRIG | MathTrig\Trig\Tangent::tan -TANH | MATH_AND_TRIG | MathTrig\Trig\Tangent::tanh -TBILLEQ | FINANCIAL | Financial\TreasuryBill::bondEquivalentYield -TBILLPRICE | FINANCIAL | Financial\TreasuryBill::price -TBILLYIELD | FINANCIAL | Financial\TreasuryBill::yield -TDIST | STATISTICAL | Statistical\Distributions\StudentT::distribution -TEXT | TEXT_AND_DATA | TextData\Format::TEXTFORMAT -TEXTAFTER | TEXT_AND_DATA | TextData\Extract::after -TEXTBEFORE | TEXT_AND_DATA | TextData\Extract::before -TEXTJOIN | TEXT_AND_DATA | TextData\Concatenate::TEXTJOIN -TEXTSPLIT | TEXT_AND_DATA | TextData\Text::split -THAIDAYOFWEEK | DATE_AND_TIME | **Not yet Implemented** -THAIDIGIT | TEXT_AND_DATA | **Not yet Implemented** -THAIMONTHOFYEAR | DATE_AND_TIME | **Not yet Implemented** -THAINUMSOUND | TEXT_AND_DATA | **Not yet Implemented** -THAINUMSTRING | TEXT_AND_DATA | **Not yet Implemented** -THAISTRINGLENGTH | TEXT_AND_DATA | **Not yet Implemented** -THAIYEAR | DATE_AND_TIME | **Not yet Implemented** -TIME | DATE_AND_TIME | DateTimeExcel\Time::fromHMS -TIMEVALUE | DATE_AND_TIME | DateTimeExcel\TimeValue::fromString -TINV | STATISTICAL | Statistical\Distributions\StudentT::inverse -TOCOL | LOOKUP_AND_REFERENCE | LookupRef\TorowTocol::tocol -TODAY | DATE_AND_TIME | DateTimeExcel\Current::today -TOROW | LOOKUP_AND_REFERENCE | LookupRef\TorowTocol::torow -TRANSPOSE | LOOKUP_AND_REFERENCE | LookupRef\Matrix::transpose -TREND | STATISTICAL | Statistical\Trends::TREND -TRIM | TEXT_AND_DATA | TextData\Trim::spaces -TRIMMEAN | STATISTICAL | Statistical\Averages\Mean::trim -TRUE | LOGICAL | Logical\Boolean::TRUE -TRUNC | MATH_AND_TRIG | MathTrig\Trunc::evaluate -TTEST | STATISTICAL | **Not yet Implemented** -TYPE | INFORMATION | Information\Value::type - -## U - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -UNICHAR | TEXT_AND_DATA | TextData\CharacterConvert::character -UNICODE | TEXT_AND_DATA | TextData\CharacterConvert::code -UNIQUE | LOOKUP_AND_REFERENCE | LookupRef\Unique::unique -UPPER | TEXT_AND_DATA | TextData\CaseConvert::upper -USDOLLAR | FINANCIAL | Financial\Dollar::format - -## V - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -VALUE | TEXT_AND_DATA | TextData\Format::VALUE -VALUETOTEXT | TEXT_AND_DATA | TextData\Format::valueToText -VAR | STATISTICAL | Statistical\Variances::VAR -VAR.P | STATISTICAL | Statistical\Variances::VARP -VAR.S | STATISTICAL | Statistical\Variances::VAR -VARA | STATISTICAL | Statistical\Variances::VARA -VARP | STATISTICAL | Statistical\Variances::VARP -VARPA | STATISTICAL | Statistical\Variances::VARPA -VDB | FINANCIAL | **Not yet Implemented** -VLOOKUP | LOOKUP_AND_REFERENCE | LookupRef\VLookup::lookup -VSTACK | LOOKUP_AND_REFERENCE | LookupRef\Vstack::vstack - -## W - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -WEBSERVICE | WEB | Web\Service::webService -WEEKDAY | DATE_AND_TIME | DateTimeExcel\Week::day -WEEKNUM | DATE_AND_TIME | DateTimeExcel\Week::number -WEIBULL | STATISTICAL | Statistical\Distributions\Weibull::distribution -WEIBULL.DIST | STATISTICAL | Statistical\Distributions\Weibull::distribution -WORKDAY | DATE_AND_TIME | DateTimeExcel\WorkDay::date -WORKDAY.INTL | DATE_AND_TIME | **Not yet Implemented** -WRAPCOLS | MATH_AND_TRIG | **Not yet Implemented** -WRAPROWS | MATH_AND_TRIG | **Not yet Implemented** - -## X - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -XIRR | FINANCIAL | Financial\CashFlow\Variable\NonPeriodic::rate -XLOOKUP | LOOKUP_AND_REFERENCE | **Not yet Implemented** -XMATCH | LOOKUP_AND_REFERENCE | **Not yet Implemented** -XNPV | FINANCIAL | Financial\CashFlow\Variable\NonPeriodic::presentValue -XOR | LOGICAL | Logical\Operations::logicalXor - -## Y - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -YEAR | DATE_AND_TIME | DateTimeExcel\DateParts::year -YEARFRAC | DATE_AND_TIME | DateTimeExcel\YearFrac::fraction -YIELD | FINANCIAL | **Not yet Implemented** -YIELDDISC | FINANCIAL | Financial\Securities\Yields::yieldDiscounted -YIELDMAT | FINANCIAL | Financial\Securities\Yields::yieldAtMaturity - -## Z - -Excel Function | Category | PhpSpreadsheet Function --------------------------|-----------------------|-------------------------------------- -Z.TEST | STATISTICAL | Statistical\Distributions\StandardNormal::zTest -ZTEST | STATISTICAL | Statistical\Distributions\StandardNormal::zTest diff --git a/docs/references/function-list-by-name.md b/docs/references/function-list-by-name.md index 35594a7109..a8caca6c79 100644 --- a/docs/references/function-list-by-name.md +++ b/docs/references/function-list-by-name.md @@ -1,659 +1,521 @@ # Function list by name -A more compact list can be found [here](./function-list-by-name-compact.md) - - ## A -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -ABS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Absolute::evaluate -ACCRINT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\AccruedInterest::periodic -ACCRINTM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\AccruedInterest::atMaturity -ACOS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::acos -ACOSH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::acosh -ACOT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::acot -ACOTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::acoth -ADDRESS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Address::cell -AGGREGATE | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -AMORDEGRC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORDEGRC -AMORLINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Amortization::AMORLINC -ANCHORARRAY | CATEGORY_MICROSOFT_INTERNAL | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::anchorArray -AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalAnd -ARABIC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Arabic::evaluate -AREAS | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** -ARRAYTOTEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::fromArray -ASC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -ASIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::asin -ASINH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::asinh -ATAN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atan -ATAN2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atan2 -ATANH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::atanh -AVEDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::averageDeviations -AVERAGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::average -AVERAGEA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::averageA -AVERAGEIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::AVERAGEIF -AVERAGEIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::AVERAGEIFS +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +ABS | CATEGORY_MATH_AND_TRIG | abs +ACCRINT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINT +ACCRINTM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ACCRINTM +ACOS | CATEGORY_MATH_AND_TRIG | acos +ACOSH | CATEGORY_MATH_AND_TRIG | acosh +ACOT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOT +ACOTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ACOTH +ADDRESS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CELL_ADDRESS +AMORDEGRC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORDEGRC +AMORLINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::AMORLINC +AND | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalAnd +AREAS | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** +ASC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** +ASIN | CATEGORY_MATH_AND_TRIG | asin +ASINH | CATEGORY_MATH_AND_TRIG | asinh +ATAN | CATEGORY_MATH_AND_TRIG | atan +ATAN2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::REVERSE_ATAN2 +ATANH | CATEGORY_MATH_AND_TRIG | atanh +AVEDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVEDEV +AVERAGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGE +AVERAGEA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEA +AVERAGEIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::AVERAGEIF +AVERAGEIFS | CATEGORY_STATISTICAL | **Not yet Implemented** ## B -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -BASE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Base::evaluate -BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselI::BESSELI -BESSELJ | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselJ::BESSELJ -BESSELK | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselK::BESSELK -BESSELY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselY::BESSELY -BETA.DIST | CATEGORY_STATISTICAL | **Not yet Implemented** -BETA.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::inverse -BETADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::distribution -BETAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Beta::inverse -BIN2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toDecimal -BIN2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toHex -BIN2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertBinary::toOctal -BINOM.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::distribution -BINOM.DIST.RANGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::range -BINOM.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::inverse -BINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::distribution -BITAND | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITAND -BITLSHIFT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITLSHIFT -BITOR | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITOR -BITRSHIFT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITRSHIFT -BITXOR | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BitWise::BITXOR -BYCOL | CATEGORY_LOGICAL | **Not yet Implemented** -BYROW | CATEGORY_LOGICAL | **Not yet Implemented** +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** +BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELI +BESSELJ | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELJ +BESSELK | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELK +BESSELY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BESSELY +BETADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETADIST +BETAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BETAINV +BIN2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTODEC +BIN2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOHEX +BIN2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::BINTOOCT +BINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::BINOMDIST ## C -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -CEILING | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::ceiling -CEILING.MATH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::math -CEILING.PRECISE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Ceiling::precise -CELL | CATEGORY_INFORMATION | **Not yet Implemented** -CHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character -CHIDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionRightTail -CHIINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionLeftTail -CHISQ.DIST.RT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::distributionRightTail -CHISQ.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseLeftTail -CHISQ.INV.RT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::inverseRightTail -CHISQ.TEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::test -CHITEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\ChiSquared::test -CHOOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Selection::CHOOSE -CHOOSECOLS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::chooseCols -CHOOSEROWS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::chooseRows -CLEAN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::nonPrintable -CODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code -COLUMN | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::COLUMN -COLUMNS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::COLUMNS -COMBIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Combinations::withoutRepetition -COMBINA | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Combinations::withRepetition -COMPLEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::COMPLEX -CONCAT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::CONCATENATE -CONCATENATE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::actualCONCATENATE -CONFIDENCE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Confidence::CONFIDENCE -CONFIDENCE.NORM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Confidence::CONFIDENCE -CONFIDENCE.T | CATEGORY_STATISTICAL | **Not yet Implemented** -CONVERT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertUOM::CONVERT -CORREL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::CORREL -COS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::cos -COSH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosine::cosh -COT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::cot -COTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cotangent::coth -COUNT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNT -COUNTA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNTA -COUNTBLANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts::COUNTBLANK -COUNTIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::COUNTIF -COUNTIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::COUNTIFS -COUPDAYBS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYBS -COUPDAYS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYS -COUPDAYSNC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPDAYSNC -COUPNCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPNCD -COUPNUM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPNUM -COUPPCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Coupons::COUPPCD -COVAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::COVAR -COVARIANCE.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::COVAR -COVARIANCE.S | CATEGORY_STATISTICAL | **Not yet Implemented** -CRITBINOM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::inverse -CSC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosecant::csc -CSCH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Cosecant::csch -CUBEKPIMEMBER | CATEGORY_CUBE | **Not yet Implemented** -CUBEMEMBER | CATEGORY_CUBE | **Not yet Implemented** -CUBEMEMBERPROPERTY | CATEGORY_CUBE | **Not yet Implemented** -CUBERANKEDMEMBER | CATEGORY_CUBE | **Not yet Implemented** -CUBESET | CATEGORY_CUBE | **Not yet Implemented** -CUBESETCOUNT | CATEGORY_CUBE | **Not yet Implemented** -CUBEVALUE | CATEGORY_CUBE | **Not yet Implemented** -CUMIPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Cumulative::interest -CUMPRINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Cumulative::principal +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +CEILING | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CEILING +CELL | CATEGORY_INFORMATION | **Not yet Implemented** +CHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER +CHIDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIDIST +CHIINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CHIINV +CHITEST | CATEGORY_STATISTICAL | **Not yet Implemented** +CHOOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::CHOOSE +CLEAN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMNONPRINTABLE +CODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE +COLUMN | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMN +COLUMNS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::COLUMNS +COMBIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COMBIN +COMPLEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::COMPLEX +CONCAT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE +CONCATENATE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CONCATENATE +CONFIDENCE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CONFIDENCE +CONVERT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::CONVERTUOM +CORREL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL +COS | CATEGORY_MATH_AND_TRIG | cos +COSH | CATEGORY_MATH_AND_TRIG | cosh +COT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COT +COTH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::COTH +COUNT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNT +COUNTA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTA +COUNTBLANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTBLANK +COUNTIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COUNTIF +COUNTIFS | CATEGORY_STATISTICAL | **Not yet Implemented** +COUPDAYBS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYBS +COUPDAYS | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYS +COUPDAYSNC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPDAYSNC +COUPNCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNCD +COUPNUM | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPNUM +COUPPCD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::COUPPCD +COVAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::COVAR +CRITBINOM | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CRITBINOM +CSC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSC +CSCH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::CSCH +CUBEKPIMEMBER | CATEGORY_CUBE | **Not yet Implemented** +CUBEMEMBER | CATEGORY_CUBE | **Not yet Implemented** +CUBEMEMBERPROPERTY | CATEGORY_CUBE | **Not yet Implemented** +CUBERANKEDMEMBER | CATEGORY_CUBE | **Not yet Implemented** +CUBESET | CATEGORY_CUBE | **Not yet Implemented** +CUBESETCOUNT | CATEGORY_CUBE | **Not yet Implemented** +CUBEVALUE | CATEGORY_CUBE | **Not yet Implemented** +CUMIPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::CUMIPMT +CUMPRINC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::CUMPRINC ## D -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -DATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Date::fromYMD -DATEDIF | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Difference::interval -DATESTRING | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -DATEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateValue::fromString -DAVERAGE | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DAverage::evaluate -DAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::day -DAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Days::between -DAYS360 | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Days360::between -DB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::DB -DBCS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -DCOUNT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DCount::evaluate -DCOUNTA | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DCountA::evaluate -DDB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::DDB -DEC2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toBinary -DEC2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toHex -DEC2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertDecimal::toOctal -DECIMAL | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -DEGREES | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Angle::toDegrees -DELTA | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Compare::DELTA -DEVSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::sumSquares -DGET | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DGet::evaluate -DISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Rates::discount -DMAX | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DMax::evaluate -DMIN | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DMin::evaluate -DOLLAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::DOLLAR -DOLLARDE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::decimal -DOLLARFR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::fractional -DPRODUCT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DProduct::evaluate -DROP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::drop -DSTDEV | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DStDev::evaluate -DSTDEVP | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DStDevP::evaluate -DSUM | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DSum::evaluate -DURATION | CATEGORY_FINANCIAL | **Not yet Implemented** -DVAR | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DVar::evaluate -DVARP | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database\DVarP::evaluate +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +DATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATE +DATEDIF | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEDIF +DATEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATEVALUE +DAVERAGE | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DAVERAGE +DAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYOFMONTH +DAYS360 | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DAYS360 +DB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DB +DCOUNT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNT +DCOUNTA | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DCOUNTA +DDB | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DDB +DEC2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOBIN +DEC2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOHEX +DEC2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DECTOOCT +DEGREES | CATEGORY_MATH_AND_TRIG | rad2deg +DELTA | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::DELTA +DEVSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::DEVSQ +DGET | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DGET +DISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DISC +DMAX | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DMAX +DMIN | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DMIN +DOLLAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::DOLLAR +DOLLARDE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DOLLARDE +DOLLARFR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::DOLLARFR +DPRODUCT | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DPRODUCT +DSTDEV | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSTDEV +DSTDEVP | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSTDEVP +DSUM | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DSUM +DURATION | CATEGORY_FINANCIAL | **Not yet Implemented** +DVAR | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DVAR +DVARP | CATEGORY_DATABASE | \PhpOffice\PhpSpreadsheet\Calculation\Database::DVARP ## E -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -ECMA.CEILING | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -EDATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month::adjust -EFFECT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\InterestRate::effective -ENCODEURL | CATEGORY_WEB | \PhpOffice\PhpSpreadsheet\Calculation\Web\Service::urlEncode -EOMONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month::lastDay -ERF | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Erf::ERF -ERF.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Erf::ERFPRECISE -ERFC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ErfC::ERFC -ERFC.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ErfC::ERFC -ERROR.TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError::type -EVEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::even -EXACT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::exact -EXP | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp::evaluate -EXPAND | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::expand -EXPON.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Exponential::distribution -EXPONDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Exponential::distribution +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +EDATE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EDATE +EFFECT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::EFFECT +EOMONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::EOMONTH +ERF | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERF +ERF.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFPRECISE +ERFC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC +ERFC.PRECISE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::ERFC +ERROR.TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::ERROR_TYPE +EVEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::EVEN +EXACT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::EXACT +EXP | CATEGORY_MATH_AND_TRIG | exp +EXPONDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::EXPONDIST ## F -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -F.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\F::distribution -F.DIST.RT | CATEGORY_STATISTICAL | **Not yet Implemented** -F.INV | CATEGORY_STATISTICAL | **Not yet Implemented** -F.INV.RT | CATEGORY_STATISTICAL | **Not yet Implemented** -F.TEST | CATEGORY_STATISTICAL | **Not yet Implemented** -FACT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::fact -FACTDOUBLE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::factDouble -FALSE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean::FALSE -FDIST | CATEGORY_STATISTICAL | **Not yet Implemented** -FILTER | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Filter::filter -FILTERXML | CATEGORY_WEB | **Not yet Implemented** -FIND | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::sensitive -FINDB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::sensitive -FINV | CATEGORY_STATISTICAL | **Not yet Implemented** -FISHER | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Fisher::distribution -FISHERINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Fisher::inverse -FIXED | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::FIXEDFORMAT -FLOOR | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::floor -FLOOR.MATH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::math -FLOOR.PRECISE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Floor::precise -FORECAST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::FORECAST -FORECAST.ETS | CATEGORY_STATISTICAL | **Not yet Implemented** -FORECAST.ETS.CONFINT | CATEGORY_STATISTICAL | **Not yet Implemented** -FORECAST.ETS.SEASONALITY | CATEGORY_STATISTICAL | **Not yet Implemented** -FORECAST.ETS.STAT | CATEGORY_STATISTICAL | **Not yet Implemented** -FORECAST.LINEAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::FORECAST -FORMULATEXT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Formula::text -FREQUENCY | CATEGORY_STATISTICAL | **Not yet Implemented** -FTEST | CATEGORY_STATISTICAL | **Not yet Implemented** -FV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::futureValue -FVSCHEDULE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::futureValue +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +FACT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACT +FACTDOUBLE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::FACTDOUBLE +FALSE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::FALSE +FDIST | CATEGORY_STATISTICAL | **Not yet Implemented** +FIND | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE +FINDB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHSENSITIVE +FINV | CATEGORY_STATISTICAL | **Not yet Implemented** +FISHER | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FISHER +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 +FORECAST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::FORECAST +FORMULATEXT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::FORMULATEXT +FREQUENCY | CATEGORY_STATISTICAL | **Not yet Implemented** +FTEST | CATEGORY_STATISTICAL | **Not yet Implemented** +FV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FV +FVSCHEDULE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::FVSCHEDULE ## G -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -GAMMA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::gamma -GAMMA.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::distribution -GAMMA.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::inverse -GAMMADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::distribution -GAMMAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::inverse -GAMMALN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::ln -GAMMALN.PRECISE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Gamma::ln -GAUSS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::gauss -GCD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Gcd::evaluate -GEOMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::geometric -GESTEP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Compare::GESTEP -GETPIVOTDATA | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** -GROUPBY | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** -GROWTH | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::GROWTH +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +GAMMADIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMADIST +GAMMAINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMAINV +GAMMALN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GAMMALN +GCD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::GCD +GEOMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GEOMEAN +GESTEP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::GESTEP +GETPIVOTDATA | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** +GROWTH | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::GROWTH ## H -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -HARMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::harmonic -HEX2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toBinary -HEX2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toDecimal -HEX2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertHex::toOctal -HLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\HLookup::lookup -HOUR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::hour -HSTACK | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Hstack::hstack -HYPERLINK | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Hyperlink::set -HYPGEOM.DIST | CATEGORY_STATISTICAL | **Not yet Implemented** -HYPGEOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\HyperGeometric::distribution +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +HARMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HARMEAN +HEX2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOBIN +HEX2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTODEC +HEX2OCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::HEXTOOCT +HLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HLOOKUP +HOUR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::HOUROFDAY +HYPERLINK | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::HYPERLINK +HYPGEOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::HYPGEOMDIST ## I -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -IF | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::statementIf -IFERROR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFERROR -IFNA | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFNA -IFS | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::IFS -IMABS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMABS -IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::IMAGINARY -IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMARGUMENT -IMCONJUGATE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCONJUGATE -IMCOS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOS -IMCOSH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOSH -IMCOT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCOT -IMCSC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCSC -IMCSCH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMCSCH -IMDIV | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMDIV -IMEXP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMEXP -IMLN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLN -IMLOG10 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLOG10 -IMLOG2 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMLOG2 -IMPOWER | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMPOWER -IMPRODUCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMPRODUCT -IMREAL | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Complex::IMREAL -IMSEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSEC -IMSECH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSECH -IMSIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSIN -IMSINH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSINH -IMSQRT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMSQRT -IMSUB | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMSUB -IMSUM | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexOperations::IMSUM -IMTAN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ComplexFunctions::IMTAN -INDEX | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix::index -INDIRECT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Indirect::INDIRECT -INFO | CATEGORY_INFORMATION | **Not yet Implemented** -INT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\IntClass::evaluate -INTERCEPT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::INTERCEPT -INTRATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Rates::interest -IPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::payment -IRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::rate -ISBLANK | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isBlank -ISERR | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isErr -ISERROR | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isError -ISEVEN | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isEven -ISFORMULA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isFormula -ISLOGICAL | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isLogical -ISNA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue::isNa -ISNONTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isNonText -ISNUMBER | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isNumber -ISO.CEILING | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -ISODD | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isOdd -ISOMITTED | CATEGORY_INFORMATION | **Not yet Implemented** -ISOWEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::isoWeekNumber -ISPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::schedulePayment -ISREF | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isRef -ISTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::isText -ISTHAIDIGIT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +IF | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::STATEMENT_IF +IFERROR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::IFERROR +IMABS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMABS +IMAGINARY | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMAGINARY +IMARGUMENT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMARGUMENT +IMCONJUGATE | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCONJUGATE +IMCOS | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOS +IMCOSH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOSH +IMCOT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCOT +IMCSC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSC +IMCSCH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMCSCH +IMDIV | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMDIV +IMEXP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMEXP +IMLN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLN +IMLOG10 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLOG10 +IMLOG2 | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMLOG2 +IMPOWER | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPOWER +IMPRODUCT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMPRODUCT +IMREAL | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMREAL +IMSEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSEC +IMSECH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSECH +IMSIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSIN +IMSINH | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSINH +IMSQRT | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSQRT +IMSUB | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUB +IMSUM | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMSUM +IMTAN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::IMTAN +INDEX | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDEX +INDIRECT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::INDIRECT +INFO | CATEGORY_INFORMATION | **Not yet Implemented** +INT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::INT +INTERCEPT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::INTERCEPT +INTRATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::INTRATE +IPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::IPMT +IRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::IRR +ISBLANK | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_BLANK +ISERR | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ERR +ISERROR | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ERROR +ISEVEN | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_EVEN +ISFORMULA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::ISFORMULA +ISLOGICAL | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_LOGICAL +ISNA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NA +ISNONTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NONTEXT +ISNUMBER | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_NUMBER +ISODD | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_ODD +ISOWEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::ISOWEEKNUM +ISPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::ISPMT +ISREF | CATEGORY_INFORMATION | **Not yet Implemented** +ISTEXT | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::IS_TEXT ## J -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -JIS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +JIS | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** ## K -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -KURT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::kurtosis +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +KURT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::KURT ## L -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -LAMBDA | CATEGORY_LOGICAL | **Not yet Implemented** -LARGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Size::large -LCM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Lcm::evaluate -LEFT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::left -LEFTB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::left -LEN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::length -LENB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::length -LET | CATEGORY_LOGICAL | **Not yet Implemented** -LINEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::LINEST -LN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::natural -LOG | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::withBase -LOG10 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Logarithms::base10 -LOGEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::LOGEST -LOGINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::inverse -LOGNORM.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::distribution -LOGNORM.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::inverse -LOGNORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\LogNormal::cumulative -LOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Lookup::lookup -LOWER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::lower +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +LARGE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LARGE +LCM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LCM +LEFT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT +LEFTB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LEFT +LEN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::STRINGLENGTH +LENB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::STRINGLENGTH +LINEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LINEST +LN | CATEGORY_MATH_AND_TRIG | log +LOG | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::LOG_BASE +LOG10 | CATEGORY_MATH_AND_TRIG | log10 +LOGEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGEST +LOGINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGINV +LOGNORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::LOGNORMDIST +LOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::LOOKUP +LOWER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::LOWERCASE ## M -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -MAKEARRAY | CATEGORY_LOGICAL | **Not yet Implemented** -MAP | CATEGORY_LOGICAL | **Not yet Implemented** -MATCH | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ExcelMatch::MATCH -MAX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum::max -MAXA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Maximum::maxA -MAXIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::MAXIFS -MDETERM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::determinant -MDURATION | CATEGORY_FINANCIAL | **Not yet Implemented** -MEDIAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::median -MEDIANIF | CATEGORY_STATISTICAL | **Not yet Implemented** -MID | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::mid -MIDB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::mid -MIN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum::min -MINA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum::minA -MINIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::MINIFS -MINUTE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::minute -MINVERSE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::inverse -MIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::modifiedRate -MMULT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::multiply -MOD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::mod -MODE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::mode -MODE.MULT | CATEGORY_STATISTICAL | **Not yet Implemented** -MODE.SNGL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages::mode -MONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::month -MROUND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::multiple -MULTINOMIAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Factorial::multinomial -MUNIT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::identity +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +MATCH | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::MATCH +MAX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAX +MAXA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXA +MAXIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MAXIF +MDETERM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MDETERM +MDURATION | CATEGORY_FINANCIAL | **Not yet Implemented** +MEDIAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MEDIAN +MEDIANIF | CATEGORY_STATISTICAL | **Not yet Implemented** +MID | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::MID +MIDB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::MID +MIN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MIN +MINA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINA +MINIF | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MINIF +MINUTE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MINUTE +MINVERSE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MINVERSE +MIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::MIRR +MMULT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MMULT +MOD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MOD +MODE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE +MODE.SNGL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::MODE +MONTH | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::MONTHOFYEAR +MROUND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MROUND +MULTINOMIAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::MULTINOMIAL ## N -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -N | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::asNumber -NA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError::NA -NEGBINOM.DIST | CATEGORY_STATISTICAL | **Not yet Implemented** -NEGBINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Binomial::negative -NETWORKDAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\NetworkDays::count -NETWORKDAYS.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -NOMINAL | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\InterestRate::nominal -NORM.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::distribution -NORM.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::inverse -NORM.S.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::distribution -NORM.S.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::inverse -NORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::distribution -NORMINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Normal::inverse -NORMSDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::cumulative -NORMSINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::inverse -NOT | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::NOT -NOW | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Current::now -NPER | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::periods -NPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\Periodic::presentValue -NUMBERSTRING | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -NUMBERVALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::NUMBERVALUE +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +N | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::N +NA | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::NA +NEGBINOMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NEGBINOMDIST +NETWORKDAYS | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::NETWORKDAYS +NOMINAL | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NOMINAL +NORMDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMDIST +NORMINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMINV +NORMSDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSDIST +NORMSINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::NORMSINV +NOT | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::NOT +NOW | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATETIMENOW +NPER | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPER +NPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::NPV +NUMBERVALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::NUMBERVALUE ## O -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -OCT2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toBinary -OCT2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toDecimal -OCT2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\ConvertOctal::toHex -ODD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::odd -ODDFPRICE | CATEGORY_FINANCIAL | **Not yet Implemented** -ODDFYIELD | CATEGORY_FINANCIAL | **Not yet Implemented** -ODDLPRICE | CATEGORY_FINANCIAL | **Not yet Implemented** -ODDLYIELD | CATEGORY_FINANCIAL | **Not yet Implemented** -OFFSET | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Offset::OFFSET -OR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalOr +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +OCT2BIN | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOBIN +OCT2DEC | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTODEC +OCT2HEX | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering::OCTTOHEX +ODD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ODD +ODDFPRICE | CATEGORY_FINANCIAL | **Not yet Implemented** +ODDFYIELD | CATEGORY_FINANCIAL | **Not yet Implemented** +ODDLPRICE | CATEGORY_FINANCIAL | **Not yet Implemented** +ODDLYIELD | CATEGORY_FINANCIAL | **Not yet Implemented** +OFFSET | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::OFFSET +OR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalOr ## P -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -PDURATION | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::periods -PEARSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::CORREL -PERCENTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTILE -PERCENTILE.EXC | CATEGORY_STATISTICAL | **Not yet Implemented** -PERCENTILE.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTILE -PERCENTRANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTRANK -PERCENTRANK.EXC | CATEGORY_STATISTICAL | **Not yet Implemented** -PERCENTRANK.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::PERCENTRANK -PERMUT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations::PERMUT -PERMUTATIONA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Permutations::PERMUTATIONA -PHI | CATEGORY_STATISTICAL | **Not yet Implemented** -PHONETIC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -PI | CATEGORY_MATH_AND_TRIG | pi -PMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Payments::annuity -POISSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Poisson::distribution -POISSON.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Poisson::distribution -POWER | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::power -PPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Payments::interestPayment -PRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::price -PRICEDISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::priceDiscounted -PRICEMAT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::priceAtMaturity -PROB | CATEGORY_STATISTICAL | **Not yet Implemented** -PRODUCT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::product -PROPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::proper -PV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic::presentValue +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +PDURATION | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PDURATION +PEARSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::CORREL +PERCENTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTILE +PERCENTRANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERCENTRANK +PERMUT | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::PERMUT +PHONETIC | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** +PI | CATEGORY_MATH_AND_TRIG | pi +PMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PMT +POISSON | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::POISSON +POWER | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::POWER +PPMT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PPMT +PRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICE +PRICEDISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICEDISC +PRICEMAT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PRICEMAT +PROB | CATEGORY_STATISTICAL | **Not yet Implemented** +PRODUCT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::PRODUCT +PROPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::PROPERCASE +PV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::PV ## Q -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -QUARTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::QUARTILE -QUARTILE.EXC | CATEGORY_STATISTICAL | **Not yet Implemented** -QUARTILE.INC | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::QUARTILE -QUOTIENT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Operations::quotient +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +QUARTILE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::QUARTILE +QUOTIENT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::QUOTIENT ## R -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -RADIANS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Angle::toRadians -RAND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::rand -RANDARRAY | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::randArray -RANDBETWEEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Random::randBetween -RANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::RANK -RANK.AVG | CATEGORY_STATISTICAL | **Not yet Implemented** -RANK.EQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles::RANK -RATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Constant\Periodic\Interest::rate -RECEIVED | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Price::received -REDUCE | CATEGORY_LOGICAL | **Not yet Implemented** -REPLACE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::replace -REPLACEB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::replace -REPT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::builtinREPT -RIGHT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::right -RIGHTB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::right -ROMAN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Roman::evaluate -ROUND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::round -ROUNDBAHTDOWN | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -ROUNDBAHTUP | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -ROUNDDOWN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::down -ROUNDUP | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Round::up -ROW | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::ROW -ROWS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\RowColumnInformation::ROWS -RRI | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Single::interestRate -RSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::RSQ -RTD | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +RADIANS | CATEGORY_MATH_AND_TRIG | deg2rad +RAND | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND +RANDBETWEEN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::RAND +RANK | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RANK +RATE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RATE +RECEIVED | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RECEIVED +REPLACE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE +REPLACEB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::REPLACE +REPT | CATEGORY_TEXT_AND_DATA | str_repeat +RIGHT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RIGHT +RIGHTB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RIGHT +ROMAN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROMAN +ROUND | CATEGORY_MATH_AND_TRIG | round +ROUNDDOWN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROUNDDOWN +ROUNDUP | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::ROUNDUP +ROW | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROW +ROWS | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::ROWS +RRI | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::RRI +RSQ | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::RSQ +RTD | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** ## S -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -SCAN | CATEGORY_LOGICAL | **Not yet Implemented** -SEARCH | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::insensitive -SEARCHB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Search::insensitive -SEC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Secant::sec -SECH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Secant::sech -SECOND | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeParts::second -SEQUENCE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\MatrixFunctions::sequence -SERIESSUM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SeriesSum::evaluate -SHEET | CATEGORY_INFORMATION | **Not yet Implemented** -SHEETS | CATEGORY_INFORMATION | **Not yet Implemented** -SIGN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sign::evaluate -SIN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sin -SINGLE | CATEGORY_MICROSOFT_INTERNAL | \PhpOffice\PhpSpreadsheet\Calculation\Internal\ExcelArrayPseudoFunctions::single -SINH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Sine::sinh -SKEW | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Deviations::skew -SKEW.P | CATEGORY_STATISTICAL | **Not yet Implemented** -SLN | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::SLN -SLOPE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::SLOPE -SMALL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Size::small -SORT | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Sort::sort -SORTBY | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Sort::sortBy -SQRT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sqrt::sqrt -SQRTPI | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sqrt::pi -STANDARDIZE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Standardize::execute -STDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEV -STDEV.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVP -STDEV.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEV -STDEVA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVA -STDEVP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVP -STDEVPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations::STDEVPA -STEYX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::STEYX -SUBSTITUTE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Replace::substitute -SUBTOTAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Subtotal::evaluate -SUM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sum::sumErroringStrings -SUMIF | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::SUMIF -SUMIFS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Conditional::SUMIFS -SUMPRODUCT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Sum::product -SUMSQ | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumSquare -SUMX2MY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXSquaredMinusYSquared -SUMX2PY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXSquaredPlusYSquared -SUMXMY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\SumSquares::sumXMinusYSquared -SWITCH | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Conditional::statementSwitch -SYD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Depreciation::SYD +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +SEARCH | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE +SEARCHB | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SEARCHINSENSITIVE +SEC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SEC +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 +SIGN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SIGN +SIN | CATEGORY_MATH_AND_TRIG | sin +SINH | CATEGORY_MATH_AND_TRIG | sinh +SKEW | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SKEW +SLN | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SLN +SLOPE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SLOPE +SMALL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::SMALL +SQRT | CATEGORY_MATH_AND_TRIG | sqrt +SQRTPI | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SQRTPI +STANDARDIZE | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STANDARDIZE +STDEV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV +STDEV.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEV +STDEV.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP +STDEVA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVA +STDEVP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVP +STDEVPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STDEVPA +STEYX | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::STEYX +SUBSTITUTE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::SUBSTITUTE +SUBTOTAL | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUBTOTAL +SUM | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUM +SUMIF | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMIF +SUMIFS | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMIFS +SUMPRODUCT | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMPRODUCT +SUMSQ | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMSQ +SUMX2MY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMX2MY2 +SUMX2PY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMX2PY2 +SUMXMY2 | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::SUMXMY2 +SYD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::SYD ## T -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -T | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::test -T.DIST | CATEGORY_STATISTICAL | **Not yet Implemented** -T.DIST.2T | CATEGORY_STATISTICAL | **Not yet Implemented** -T.DIST.RT | CATEGORY_STATISTICAL | **Not yet Implemented** -T.INV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::inverse -T.INV.2T | CATEGORY_STATISTICAL | **Not yet Implemented** -T.TEST | CATEGORY_STATISTICAL | **Not yet Implemented** -TAKE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\ChooseRowsEtc::take -TAN | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::tan -TANH | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trig\Tangent::tanh -TBILLEQ | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::bondEquivalentYield -TBILLPRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::price -TBILLYIELD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\TreasuryBill::yield -TDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::distribution -TEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::TEXTFORMAT -TEXTAFTER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::after -TEXTBEFORE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Extract::before -TEXTJOIN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Concatenate::TEXTJOIN -TEXTSPLIT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::split -THAIDAYOFWEEK | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -THAIDIGIT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -THAIMONTHOFYEAR | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -THAINUMSOUND | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -THAINUMSTRING | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -THAISTRINGLENGTH | CATEGORY_TEXT_AND_DATA | **Not yet Implemented** -THAIYEAR | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -TIME | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Time::fromHMS -TIMEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\TimeValue::fromString -TINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StudentT::inverse -TOCOL | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\TorowTocol::tocol -TODAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Current::today -TOROW | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\TorowTocol::torow -TRANSPOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix::transpose -TREND | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::TREND -TRIM | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::spaces -TRIMMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::trim -TRUE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Boolean::TRUE -TRUNC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Trunc::evaluate -TTEST | CATEGORY_STATISTICAL | **Not yet Implemented** -TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Information\Value::type +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +T | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::RETURNSTRING +TAN | CATEGORY_MATH_AND_TRIG | tan +TANH | CATEGORY_MATH_AND_TRIG | tanh +TBILLEQ | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLEQ +TBILLPRICE | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLPRICE +TBILLYIELD | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::TBILLYIELD +TDIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TDIST +TEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTFORMAT +TEXTJOIN | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TEXTJOIN +TIME | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIME +TIMEVALUE | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::TIMEVALUE +TINV | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TINV +TODAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::DATENOW +TRANSPOSE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::TRANSPOSE +TREND | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TREND +TRIM | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::TRIMSPACES +TRIMMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::TRIMMEAN +TRUE | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::TRUE +TRUNC | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig::TRUNC +TTEST | CATEGORY_STATISTICAL | **Not yet Implemented** +TYPE | CATEGORY_INFORMATION | \PhpOffice\PhpSpreadsheet\Calculation\Functions::TYPE ## U -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -UNICHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character -UNICODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code -UNIQUE | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Unique::unique -UPPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CaseConvert::upper -USDOLLAR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Dollar::format +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +UNICHAR | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::CHARACTER +UNICODE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::ASCIICODE +UPPER | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::UPPERCASE +USDOLLAR | CATEGORY_FINANCIAL | **Not yet Implemented** ## V -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -VALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::VALUE -VALUETOTEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::valueToText -VAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VAR -VAR.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARP -VAR.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VAR -VARA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARA -VARP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARP -VARPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances::VARPA -VDB | CATEGORY_FINANCIAL | **Not yet Implemented** -VLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\VLookup::lookup -VSTACK | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Vstack::vstack +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +VALUE | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData::VALUE +VAR | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc +VAR.P | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP +VAR.S | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARFunc +VARA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARA +VARP | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARP +VARPA | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::VARPA +VDB | CATEGORY_FINANCIAL | **Not yet Implemented** +VLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef::VLOOKUP ## W -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -WEBSERVICE | CATEGORY_WEB | \PhpOffice\PhpSpreadsheet\Calculation\Web\Service::webService -WEEKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::day -WEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week::number -WEIBULL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Weibull::distribution -WEIBULL.DIST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\Weibull::distribution -WORKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\WorkDay::date -WORKDAY.INTL | CATEGORY_DATE_AND_TIME | **Not yet Implemented** -WRAPCOLS | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** -WRAPROWS | CATEGORY_MATH_AND_TRIG | **Not yet Implemented** +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +WEEKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKDAY +WEEKNUM | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WEEKNUM +WEIBULL | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::WEIBULL +WORKDAY | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::WORKDAY ## X -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -XIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\NonPeriodic::rate -XLOOKUP | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** -XMATCH | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented** -XNPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\CashFlow\Variable\NonPeriodic::presentValue -XOR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical\Operations::logicalXor +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +XIRR | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XIRR +XNPV | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::XNPV +XOR | CATEGORY_LOGICAL | \PhpOffice\PhpSpreadsheet\Calculation\Logical::logicalXor + ## Y -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -YEAR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\DateParts::year -YEARFRAC | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\YearFrac::fraction -YIELD | CATEGORY_FINANCIAL | **Not yet Implemented** -YIELDDISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Yields::yieldDiscounted -YIELDMAT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities\Yields::yieldAtMaturity +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +YEAR | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEAR +YEARFRAC | CATEGORY_DATE_AND_TIME | \PhpOffice\PhpSpreadsheet\Calculation\DateTime::YEARFRAC +YIELD | CATEGORY_FINANCIAL | **Not yet Implemented** +YIELDDISC | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::YIELDDISC +YIELDMAT | CATEGORY_FINANCIAL | \PhpOffice\PhpSpreadsheet\Calculation\Financial::YIELDMAT ## Z -Excel Function | Category | PhpSpreadsheet Function --------------------------|--------------------------------|-------------------------------------- -Z.TEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::zTest -ZTEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions\StandardNormal::zTest +Excel Function | Category | PhpSpreadsheet Function +--------------------|--------------------------------|------------------------------------------- +ZTEST | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical::ZTEST diff --git a/docs/topics/Behind the Mask.md b/docs/topics/Behind the Mask.md deleted file mode 100644 index ba77fcc4e9..0000000000 --- a/docs/topics/Behind the Mask.md +++ /dev/null @@ -1,837 +0,0 @@ -# Behind the Mask - -When we look at a spreadsheet in MS Excel, we normally see it neatly formatted so that it is easy for a human to read. - -Internally, that spreadsheet comprises a set of values that are normally either numbers or text (occasionally boolean `TRUE` or `FALSE`); or a formula that results in a number, text or boolean value. Unlike PHP, MS Excel doesn't differentiate between `integer` or `float`; but all numbers can be presented as integer or with decimals, as dates or percentages, as currency, even made to look like telephone numbers. -A zero value can be made to look like `0` or `0.00`, like `-`, or even like a text string `zero`. Positive values can be displayed in one colour, negative values in another. - -![Stock Portfolio.png](images/Behind the Mask/Stock Portfolio.png) -Behind this Stock Portfolio table example, with the exception of the headings and the stock symbols, every value is a number; but each column is rendered in a manner that provides meaning to our human eye - -`Purchase Date` as a day-month-year date; `Purchase Price` and `Current Price` as monetary values with a currency code; `Purchase Quantity` as an integer value and `Difference` as a float with 2 decimals; `% Return` as a percentage; and `Profit/Loss` as a monetary value with a currency code, thousands separator, and negative values highlighted in red; `Stdev` with 3 decimals - -and all styled by using a Number Format Mask. - -## Reading a Cell Value - -PhpSpreadsheet provides three methods for reading a Cell value. -If we use the Cell's `getValue()` method, we are retrieving the underlying value (or the formula) for that cell. If the Cell contains a formula, then we can use the `getCalculatedValue()` method to see the result of evaluating that formula. If we want to see the value as it is displayed in MS Excel, then we need to use `getFormattedValue()`. - -Reading Cells from the Worksheet shown above: -```php -var_dump($worksheet->getCell('C4')->getValue()); -var_dump($worksheet->getCell('C4')->getCalculatedValue()); -var_dump($worksheet->getCell('C4')->getFormattedValue()); - -var_dump($worksheet->getCell('H4')->getValue()); -var_dump($worksheet->getCell('H4')->getCalculatedValue()); -var_dump($worksheet->getCell('H4')->getFormattedValue()); -``` -we see the different results for cell `C4` (a simple numeric value formatted as a Currency) and cell `H4` (a formula that evaluates to a numeric value, and formatted as a Currency): -``` -float(26.19) -float(26.19) -string(9) "€ 26.19" - -string(8) "=$F4*$D4" -float(-170) -string(11) "€ -170.00" -``` -Note that getting the formatted value will always evaluate a formula to render the result. - -### Reading a Cell's Formatting Mask - -PhpSpreadsheet also provides methods that allow us to look at the format mask itself: -```php -var_dump($worksheet->getCell('C4') - ->getStyle()->getNumberFormat()->getFormatCode()); - -var_dump($worksheet->getCell('H4') - ->getStyle()->getNumberFormat()->getFormatCode()); -``` -and we can see the Format Masks for those cells: -``` -string(20) "[$€-413]\ #,##0.00" - -string(48) "[$€-413]\ #,##0.00;[Red][$€-413]\ \-#,##0.00" -``` -> **Note**: that the space and sign in the mask are non-breaking characters, so they are rendered to output as "\ " and "\-" respectively when var_dumped. This prevents breaking the displayed value across two lines. - -## Setting a Cell's Formatting Mask - -When you are using a spreadsheet application like MS Excel, the application will try to decide what Format Mask should be used for a cell as you enter the value, based on that value and your locale settings; and with varying degrees of success. -If the value looks like a Currency, then it will be converted to a number and an appropriate Currency Mask set; similarly if you type something that looks like a percentage; and it is often a joke that Excel identifies many values as Dates (even if that was never the intent), and sets a Date Format Mask. -The default Mask if no specific type can be identified from the value is "General". - -PhpSpreadsheet doesn't do this by default. If you enter a value in a cell, then it will not convert that value from a string containing a currency symbol to a number: it will remain a string. Nor will it change any existing Format Mask: and if that value is a new cell, then it will be assigned a default Format Mask of "General". -It will convert a string value to a numeric if it looks like a number with or without decimals (but without leading zeroes), or in scientific format; but it still won't change the Format Mask. - -```php -// Set Cell C21 using a formatted string value -$worksheet->getCell('C20')->setValue('€ -1234.567'); - -// The Cell value should be the string that we set -var_dump($worksheet->getCell('C20')->getValue()); -// The Format Mask should be "General" -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); -// The formatted value should still be the string that we set -var_dump($worksheet->getCell('C20')->getFormattedValue()); - -// Set Cell C21 using a numeric value -$worksheet->getCell('C21')->setValue('-1234.567'); - -// The numeric string value should have been converted to a float -var_dump($worksheet->getCell('C21')->getValue()); -// The Format Mask should be "General" -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); -var_dump($worksheet->getCell('C21')->getFormattedValue()); - -// Change the Format Mask for C21 to a Currency mask -$worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->setFormatCode('€ #,##0;€ -#,##0'); - -// The float value should still be the same -var_dump($worksheet->getCell('C21')->getValue()); -// The Format Mask should be the new mask that we set -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); -// The value should now be formatted as a Currency -var_dump($worksheet->getCell('C21')->getFormattedValue()); -``` -giving -```php -string(13) "€ -1234.567" -string(7) "General" -string(13) "€ -1234.567" - -float(-1234.567) -string(7) "General" -string(9) "-1234.567" - -float(-1234.567) -string(20) "€ #,##0;€ -#,##0" -string(10) "€ -1,235" -``` - -If you wish to emulate the MS Excel behaviour, and automatically convert string values that represent Currency, Dates, Fractions, Percentages, etc. then the Advanced Value Binder attempts to identify these, to convert to a number, and to set an appropriate Format Mask. - -You can do this by changing the Value Binder, which will then apply every time you set a Cell value. -```php -// Old method using static property -Cell::setValueBinder(new AdvancedValueBinder()); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet->setValueBinder(new AdvancedValueBinder()); - -// Set Cell C21 using a formatted string value -$worksheet->getCell('C20')->setValue('€ -12345.6789'); - -// The Cell value is a float of -12345.6789 -var_dump($worksheet->getCell('C20')->getValue()); -// The format code is "[$€]#,##0.00_-" -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); -// The formatted value is "€-12,345.68 " -var_dump($worksheet->getCell('C20')->getFormattedValue()); -``` - -Or (since version 1.28.0) you can specify a Value Binder to use just for that one call to set the Cell's value. - -```php -// Set Cell C21 using a formatted string value, but using a Value Binder -$worksheet->getCell('C20')->setValue('€ -12345.6789', new AdvancedValueBinder()); - -// The Cell value is a float of -12345.6789 -var_dump($worksheet->getCell('C20')->getValue()); -// The format code is "[$€]#,##0.00_-" -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); -// The formatted value is "€-12,345.68 " -var_dump($worksheet->getCell('C20')->getFormattedValue()); -``` -While PhpSpreadsheet's Advanced Value Binder isn't as "sophisticated" as MS Excel at recognising formats that should be converted to numbers, or at setting a mask that exactly matches the entered value, it can simplify entering data from formatted strings; and is particularly useful when reading untyped or loosely formatted files like a CSV. - -> **Warning**: Remember that setting a Cell value explicitly bypasses the Value Binder, so you will always have to set the Format Mask manually if you are using `setValueExplicit()` to set Cell values. - -## Using Formatting Masks in the TEXT() Function - -We can also use Number Formatting Masks directly in Excel's `TEXT()` Function, without setting the mask for a Cell. - -```php -$worksheet->getCell('A1')->setValue(12345.678); -$worksheet->getCell('B1') - ->setValue('#.00" Surplus";-#.00" Deficit";"Out of Stock"'); -$worksheet->getCell('C1')->setValue('=TEXT(A1,B1)'); - -var_dump($worksheet->getCell('C1')->getCalculatedValue()); // 12,345.68 Surplus - - -$worksheet->getCell('A2')->setValue(-12345.678); -$worksheet->getCell('C2') - ->setValue('=TEXT(A2,"#,##0.00"" Surplus"";-#,##0.00"" Deficit"";""Out of Stock""")'); - -var_dump($worksheet->getCell('C2')->getCalculatedValue()); // -12,345.68 Deficit -``` -Remember that you'll need to escape double quotes in the mask argument by double double-quoting them if you pass the mask directly as an string. -It's generally easier to read if you store the mask as text in a cell, and then pass the cell reference as the mask argument. - -## Changing a Cell's Formatting Mask - -In PhpSpreadsheet we can change a Cell's Formatting Mask at any time just by setting a new FormatCode for that Cell. -The library provides a number of "pre-defined" Masks as Constants in the `NumberFormat` class, prefixed with 'FORMAT_', but isn't limited to these values - the mask itself is just a string value - and the value passed to `setFormatCode()` can be any valid Excel Format Mask string. -> **Note**: The Mask value isn't validated: it's up to you, as the developer, to ensure that you set a meaningful Mask value. - -And while Excel applies an initial Mask to every Cell when we enter a value (even if it's just the default "General"), we can still always change that Mask. -This is managed through the "Number" block in the "Home" ribbon. - -![Excel Number Format.png](images/Behind the Mask/Excel Number Format.png) - -This provides us with some simple options for increasing or decreasing the number of decimals displayed, if we want a thousands separator, a currency code to use, etc. - -But if we use the "pull down" for that block, we access the "Number" tab of "Format Cells" that provides a lot more options. - -![Excel Number Format - General.png](images/Behind the Mask/Excel Number Format - General.png) - -This gives us access to a number of "Wizards" for different "Categories" of masking, as well as "Custom", which allows us to build our own masks. - -Since version 1.28.0, PhpSpreadsheet has also provided a set of "Wizards", allowing for the easier creation of Mask values for most Categories. - -## Mask Categories - -I'll describe "Custom" Mask values later in this article; but let's take a look at the "Wizard" options for each "Category" first. - -### General - -This is the default Mask, and is "adaptive". -Numbers will appear with as many decimals as have been entered for the value (to the limit of a 9 or 10 digit display; additional decimals will be rounded), while very large or very small values will display in Scientific format. - -### Number - -Excel's Number "Wizard" allows you to specify the number of decimals, and whether to use a thousands separator (or not). -It also offers a few ways to display negative values (with or without a sign, highlighted in red). - -![Excel Number Format - Number.png](images/Behind the Mask/Excel Number Format - Number.png) - -A typical mask will look something like '0.00' (2 decimals, with no thousands separator) or '#,##0.000' (3 decimals with a thousands separator). - -The PhpSpreadsheet Number "Wizard" allows you to specify the number of decimals, and the use of a thousands separator. -The defaults are 2 decimal places, and to use a thousands separator. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Number Wizard to build the Format Mask -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode((string) new Number(3, Number::WITH_THOUSANDS_SEPARATOR)); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); // "#,##0.000" -var_dump($worksheet->getCell('C20')->getFormattedValue()); // "-12,345.679" -``` - -PhpSpreadsheet's "Wizard" doesn't yet offer options for displaying negative values; they will simply be masked so that they always display the sign. -But alternative masking for negative values is an option that may be added in the future. - -### Currency - -The Currency "Wizard" in MS Excel has similar options to the Number "Wizard", but also requires that you specify a currency code. - -![Excel Number Format - Currency.png](images/Behind the Mask/Excel Number Format - Currency.png) - -The "Symbol" dropdown provides a lot of locale-specific variants of the same currencies - for example '€ Netherlands', where the currency symbol is displayed before the value, and any negative sign appears before the currency "-€ 12,345.68"; or '€ France', where the symbol is displayed after the value "-12,345.68 €". - -The PhpSpreadsheet Currency "Wizard" allows you to specify the currency code, number of decimals, and the use of a thousands separator. -In addition, optionally, you can also specify whether the currency symbol should be leading or trailing, and whether it should be separated from the value or not. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Currency Wizard to build the Format Mask -$currencyMask = new Currency( - '€', - 2, - Number::WITH_THOUSANDS_SEPARATOR, - Currency::TRAILING_SYMBOL, - Currency::SYMBOL_WITH_SPACING -); -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode($currencyMask); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); // #,##0.00 € -var_dump($worksheet->getCell('C20')->getFormattedValue()); // -12,345.68 € -``` -A typical Currency mask might look something like '#,##0.00 €', with the currency symbol as a literal. - -The Currency Code itself may be a literal character, as here with the `€` symbol; or it can be wrapped in square braces with a `$` symbol to indicate that this is a currency and the next character as the currency symbol to use, and then (optionally) a locale code or an LCID (Locale ID) like `[$€-de-DE]` or `[$€-1031]`. - -I wouldn't recommend using LCIDs in your code, a locale code is a lot easier to recognise and understand; but if you do need to reference LCIDs, then you can find a list [here](https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a). - -Alternatively, if you have PHP's `Intl` extension installed, you can specify a currency code and a locale code. -If you use this option, then locale values must be a valid formatted locale string (e.g. `en-GB`, `fr`, `uz-Arab-AF`); and the Wizard will use the format defined in ICU (International Components for Unicode): any values that you provide for placement of the currency symbol, etc. will be ignored. -The only argument that won't be ignored is an explicit value of 0 for the decimals, which will create a mask to display only major currency units. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C21')->setValue(-12345.67890); - -// Set Cell Style using the Currency Wizard to build the Format Mask for a locale -$localeCurrencyMask = new Currency( - '€', - locale: 'de_DE' -); -$worksheet->getCell('C21') - ->getStyle()->getNumberFormat() - ->setFormatCode($localeCurrencyMask); - -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); // #,##0.00 [$€-de-DE] -var_dump($worksheet->getCell('C21')->getFormattedValue()); // -12,345.68 € -``` -If we use the locale in the "Wizard", then a typical mask might look like '#,##0.00 [$€-de-DE]', with the currency wrapped in braces, a `$` to indicate that this is a localised value, and the locale included. - > Note: The Wizard does not accept LCIDs. - -PhpSpreadsheet's "Wizard" doesn't yet offer options for displaying negative values; they will simply be masked so that they always display the sign. -But alternative masking for negative values is an option that may be added in the future. - -### Accounting - -Excel's Accounting "Wizard" is like the Currency "Wizard", but without the options for presenting negative values. -Presentation of zero and negative values is dependent on the currency and locale. - -![Excel Number Format - Accounting.png](images/Behind the Mask/Excel Number Format - Accounting.png) - -The options available for the PhpSpreadsheet Accounting "Wizard" are identical to those of the Currency "Wizard"; although the generated Mask is different. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Accounting; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Accounting Wizard to build the Format Mask -$currencyMask = new Accounting( - '€', - 2, - Number::WITH_THOUSANDS_SEPARATOR, - Currency::TRAILING_SYMBOL, - Currency::SYMBOL_WITH_SPACING -); -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode($currencyMask); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); // _-#,##0.00 €*_- -var_dump($worksheet->getCell('C20')->getFormattedValue()); // -12,345.68 € -``` -A typical Accounting mask might look something like '_-#,##0.00 €*_-', with the currency symbol as a literal; and with placement indicators like `_-`, that ensure the alignment of the currency symbols and decimal points of numbers in a column. - -At the moment, none of the PhpSpreadsheet Wizards provide different masks for zero and negative values; unless you have the PHP `Intl` extension enabled, and can use the locale to generate the Mask. -As with using a locale with the Currency "Wizard", when you use a locale with the Accounting "Wizard" the locale value must be valid, and any additional options will be ignored. -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Accounting; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C21')->setValue(-12345.67890); - -// Set Cell Style using the Accounting Wizard to build the Format Mask for a locale -$localeCurrencyMask = new Accounting( - '€', - locale: 'nl_NL' -); -$worksheet->getCell('C21') - ->getStyle()->getNumberFormat() - ->setFormatCode($localeCurrencyMask); - -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); // [$€-nl-NL] #,##0.00;([$€-nl-NL] #,##0.00) -var_dump($worksheet->getCell('C21')->getFormattedValue()); // (€ 12,345.68) -``` -If we use the locale in the "Wizard", then a typical mask might look like '[$€-nl-NL] #,##0.00;([$€-nl-NL] #,##0.00)', with the currency wrapped in braces, with a `$` to indicate that this is a localised value, and the locale included. -And in this case, there is masking for zero and for negative values, although without colour. An option to add colour to values is an option that may be added in a future release. - -> **Warning**: Not all versions of the ICU (International Components for Unicode) support Accounting formats, so even if your PHP does have 'Intl' enabled, it may still not allow the use of locale for generating an Accounting Mask. - -### Date - -When you use the Excel Date "Wizard", you can select a locale and you'll then be presented with a number of date format options that are appropriate for that locale. - -![Excel Number Format - Date.png](images/Behind the Mask/Excel Number Format - Date.png) - -I've written in detail about Date Format Masks elsewhere in "The Dating Game"; but to summarise, here are the Mask codes used for Date formatting. - -| Code | Description | Example (January 3, 2023) | -|-------|-------------------------------------|---------------------------------------| -| m | Month number without a leading zero | 1 | -| mm | Month number with a leading zero | 01 | -| mmm | Month name, short form | Jan | -| mmmm | Month name, full form | January | -| mmmmm | Month as the first letter | J (stands for January, June and July) | -| d | Day number without a leading zero | 3 | -| dd | Day number with a leading zero | 03 | -| ddd | Day of the week, short form | Tue | -| dddd | Day of the week, full form | Tuesday | -| yy | Year (last 2 digits) | 23 | -| yyyy | Year (4 digits) | 2023 | - - -There is currently no PhpSpreadsheet "Wizard" for Date Masks; but this will be introduced in the 1.29.0 release. - -### Time - -As with Dates, when you use the Excel Time "Wizard", you can select a locale and you'll then be presented with a number of time format options that are appropriate for that locale. - -![Excel Number Format - Time.png](images/Behind the Mask/Excel Number Format - Time.png) - -I've written in detail about Time Format Masks elsewhere in "The Dating Game"; but to summarise, here are the Mask codes used for Time formatting. - -| Code | Description | Displays as | -|--------|--------------------------------------------------------------------|-------------| -| h | Hours without a leading zero | 0-23 | -| hh | Hours with a leading zero | 00-23 | -| m | Minutes without a leading zero | 0-59 | -| mm | Minutes with a leading zero | 00-59 | -| s | Seconds without a leading zero | 0-59 | -| ss | Seconds with a leading zero | 00-59 | -| AM/PM | Periods of the day
(if omitted, 24-hour time format is used) | AM or PM | - -Excel also supports Masks for Time Durations, although there is no "Wizard" for this; but the following Mask codes can be used to display Durations. - -| Code | Description | Displays as | -|---------|----------------------------------------------------------------|-------------| -| [h]:mm | Elapsed time in hours | e.g. 25:02 | -| [hh]:mm | Elapsed time in hours
with a leading zero if less than 10 | e.g. 05:02 | -| [mm]:ss | Elapsed time in minutes | e.g. 63:46 | -| [m]:ss | Elapsed time in minutes
with a leading zero if less than 10 | e.g. 03:46 | -| [s] | Elapsed time in seconds | | -| [ss] | Elapsed time in seconds
with a leading zero if less than 10 | | - -There is currently no PhpSpreadsheet "Wizard" for Time Masks, or for Durations; but these will be introduced in the 1.29.0 release. - -### Percentage - -This is among the simplest of the Excel "Wizards", only allowing you to specify the number of decimals to be displayed. - -![Excel Number Format - Percentage.png](images/Behind the Mask/Excel Number Format - Percentage.png) - -The Percentage mask looks like '0.00%'. - -Using the `%` code in a mask will multiply the value by 100 before rendering it, and it will always also display the `%` sign. - -The PhpSpreadsheet "Wizard" replicates this simple option; but also provides a locale option that allows locale-specific formatting, because there are a few locales where the percentage sign appears before the value rather than after it. -As with all locale use for the PhpSpreadsheet "Wizard", this is dependent on having the `Intl` extension enabled. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Percentage; - -// Set Cell value -$worksheet->getCell('C21')->setValue(-12345.67890); - -// Set Cell Style using the Percentage Wizard to build the Format Mask for a locale -$localeCurrencyMask = new Percentage( - locale: 'tr_TR' -); -$worksheet->getCell('C21') - ->getStyle()->getNumberFormat() - ->setFormatCode($localeCurrencyMask); - -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); // %#,##0.00 -var_dump($worksheet->getCell('C21')->getFormattedValue()); // %-12,345.68 -``` - -### Fraction - -MS Excel presents two different options for fractions: the first where the denominator is calculated internally to either 1, 2 or 3 digits; and the second (introduced only recently) where the denominator is fixed as 2, 4, 8 or 16. - -![Excel Number Format - Fraction.png](images/Behind the Mask/Excel Number Format - Fraction.png) - -The Fraction mask looks like '# ?/???' where `#` indicates that the integer part of the value should be displayed, and then `?/???` to display the fraction with up to 3 digits in the denominator. -The mask using a fixed-denominator looks like '# ?/16', with the denominator value replacing the variable `?`. - -If you use digit placeholders (`/??`) for the denominator, then Excel will calculate the lowest denominator that it can use for the fractional value. If you specify a fixed denominator (e.g. `/8`) then Excel will calculate the fraction in eighths. - -> **Note:** The internal renderer in PhpSpreadsheet does not consider the number of digits for the denominator, but will simply try to identify the lowest value denominator that it can use. - -There is currently no PhpSpreadsheet "Wizard" for Fraction Masks. - -### Scientific - -This is among the simplest of the Excel "Wizards", only allowing you to specify the number of decimals to be displayed. - -![Excel Number Format - Scientific.png](images/Behind the Mask/Excel Number Format - Scientific.png) - -The Scientific mask looks like '0.00E+00'. - -> **Note**: The internal rendering used by PhpSpreadsheet will display only as many digits as necessary for the exponent; while the Excel mask specifies a minimum of 2 digits, with a leading zero if necessary. - -The PhpSpreadsheet "Wizard" replicates this simple option. -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Scientific; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Scientific Wizard to build the Format Mask -$scientificMask = new Scientific( - 4, -); -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode($scientificMask); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat()->getFormatCode()); // 0.0000E+00 -var_dump($worksheet->getCell('C20')->getFormattedValue()); // -1.2346E+4 - -// Set Cell value -$worksheet->getCell('C21')->setValue(-12345.67890); - -// Set Cell Style using the Scientific Wizard to build the Format Mask for a locale -$localeScientificMask = new Scientific( - 3, - locale: 'nl_NL' -); -$worksheet->getCell('C21') - ->getStyle()->getNumberFormat() - ->setFormatCode($localeScientificMask); - -var_dump($worksheet->getCell('C21') - ->getStyle()->getNumberFormat()->getFormatCode()); // 0.000E+00 -var_dump($worksheet->getCell('C21')->getFormattedValue()); // -1.235E+4 -``` - -If you specify a number of decimals to display, then the Scientific "Wizard" will apply that value, even when using a locale. - -### Text - -MS Excel's Text "Wizard" has no options, but simply sets a mask to `@`, meaning display the value exactly as it is entered. -Unlike `General`, which is adaptive, `@` will not change the displayed value in any way, except in one exceptional case (see note below). -Very large or very small values will not be displayed in Scientific format, and leading zeroes will be displayed. - ->**Note:** If your cell contains Rich Text, then using `@` in a format mask will display it using the basic cell styling, ignoring the Rich Text styling. - -![Excel Number Format - Text.png](images/Behind the Mask/Excel Number Format - Text.png) - -PhpSpreadsheet doesn't emulate this behaviour; it simply displays the value as PHP would render that value cast to a string, which mimics Excel's quirk with Rich Text values. - -There is no PhpSpreadsheet "Wizard" for Text Masks. - -### Special - -Excel's Special format "Wizard" is a recent introduction: select a locale, and then you may be offered a number of options for formatting values in a manner that is appropriate to that locale, such as US phone numbers, social security numbers, or zip codes; typically with separators between groups of digits. -At this time, most locales have no special formats defined. - -![Excel Number Format - Special.png](images/Behind the Mask/Excel Number Format - Special.png) - -There is no PhpSpreadsheet "Wizard" for Special Masks. - -## Custom Format Masks - -The Custom "Wizard" really isn't a Wizard at all, just an editing field that allows you to pre-populate from a list of common format masks before editing. - -![Excel Number Format - Custom.png](images/Behind the Mask/Excel Number Format - Custom.png) - -It does mean that you need to understand the rules for defining masks when you use this. - -When you create custom number formats, you can specify up to four sections of format code. -These sections of code must be separated by semicolons (`;`). - -### Sections for Composite Masks - -Sections of the mask define the formats for positive numbers, negative numbers, zero values, and text, in that order. - -![Mask Sections.png](images/Behind the Mask/Mask Sections.png) - 1. Format for Positive values - 2. Format for Negative values - 3. Format for Zero values - 4. Format for Text - -If you specify only one section of format code, the code in that section is used for all numbers. -If you specify two sections of format code, the first section of code is used for positive numbers and zeros, and the second section of code is used for negative numbers. -If you specify a third section, then the first applies to positive values, the second to negative values, and the third to zero values. -The fourth section only applies if the value is not numeric. - -If you skip code sections in the format mask, then you must include a semicolon for each of the missing sections. - -When you skip code sections in the format mask, then you must include a semicolon for each of the missing sections. Use `;` to indicate that a section exists, but with an empty mask; and that can be used to hide values that match the criteria for that section. - -![Hiding Values.png](images/Behind the Mask/Hiding Values.png) - -> **Note:** Negative values aren't shown with a sign when we use the negative value section. If we want the value to display with a sign, then we need to include an explicit '-' character in the Mask for that section (";-0;"). - -### Basic Masking Symbols - -Three basic masking symbols are used to display numbers, and they differ in the way that they display leading or trailing zeroes. -The fourth basic masking symbol is the text placeholder, which can be used to wrap the cell value within additional formatting. - -| Code | Description | Examples | -|------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 0 | Digit placeholder that displays insignificant zeros. | #.00 - always displays 2 decimal places.

If you type 5.5 in a cell, it will display as 5.50. | -| # | Digit placeholder that represents optional digits and does not display extra zeros.

That is, if a number doesn't need a certain digit, it won't be displayed. | #.## - displays up to 2 decimal places.

If you type 5.5 in a cell, it will display as 5.5.

If you type 5.555, it will display as 5.56. | -| ? | Digit placeholder that leaves a space for insignificant zeros on either side of the decimal point but doesn't display them. It is often used to align numbers in a column by decimal point. | #.??? - displays a maximum of 3 decimal places and aligns numbers in a column by decimal point. | -| @ | Text placeholder | 0.00; -0.00; 0; [Red]@ - applies the red font colour for text values. | - -If a number entered in a cell has more digits to the right of the decimal point than there are placeholders in the format, the number is "rounded" to as many decimal places as there are placeholders. -For example, if you have a value of `2.25` in a cell with '#.#' format, then the number will be rounded to 1 decimal, and will display as `2.3`. - -Digits to the left of the decimal point are always displayed regardless of the number of placeholders. -For example, if the value in a cell is `202.25` with '#.#' format, the number will display as `202.3`. - -![Digit Placeholders.png](images/Behind the Mask/Digit Placeholders.png) - -To display leading zeroes for a numeric value, you might create a mask like '0000', which will always display at least 4 digits, padding the value with leading zeroes if it is less than 1000. - -### Other Special Codes -In addition to the masking symbols listed above, the following codes also enable special rendering of the value. - -| Code | Description | Example | -|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------| -| . (period) | Decimal point. | ##0.00?? | -| , (comma) | Thousands Separator.
A comma that follows a digit placeholder scales the number by a thousand. | #,##0
0.000,
Described below. | -| \ | Text Escape Character that displays the character that follows it. | ##0\°
Described below. | -| " " | Display any text that is enclosed in the double quotes. | ##0"°C"
Described below. | -| % | Multiplies the value stored in the cell by 100 and display it with the percentage sign. | Examples provided in the "Wizard" section above. | -| / | Display the value as a fraction. | Examples provided in the "Wizard" section above. | -| E | Display the value in Scientific Format. | Examples provided in the "Wizard" section above. | -| _ (underscore) | Space pad to the width of the next character in the mask.
It is commonly used in combination with parentheses to add left and right indents, `_(` and `_)` respectively. | Described below. | -| * (asterisk) | Repeats the character that follows it until the width of the cell is filled.
It is often used in combination with the space character to change alignment. | Described below. | - -Simple examples of using these codes for Percentages, Fractions and Scientific Format can be found in the descriptions of those "Wizards". -The other codes are described in detail below. - -### Thousands Separator and Scaling - -To create an Excel custom number format with a thousands separator, include a comma (`,`) in the format code. For example: - - - #,### - display a thousands separator and no decimal places. - - #,##0.00 - display a thousands separator and 2 decimal places. - -Microsoft Excel separates thousands by commas: if a comma is enclosed by any digit placeholders - the pound sign (`#`), question mark (`?`) or zero (`0`). -But if no digit placeholder follows a comma, it scales the number by a thousand, two consecutive commas scale the number by a million, and so on. - -For example, if a cell format is '#.00,' and the cell value is `5000`, then the number `5.00` is displayed. - -![Scaling Example.png](images/Behind the Mask/Scaling Example.png) - -### Formatting with Text - -If you want to include text in your format mask with numeric values, then there are two basic options. -To add a single character, then you can prefix that character with a backslash ('\'), e.g. '#.00,\K' or '#.00,,\M'. - -![Text Single Character Example.png](images/Behind the Mask/Text Single Character Example.png) - -You don't need the backslash ('\') prefix for the following list of characters: - -| Character | Description | -|-----------|----------------------------------| -| + and - | Plus and Minus Signs | -| ( and ) | Left and Right Parenthesis | -| : | Colon | -| ^ | Caret | -| ' | Apostrophe | -| { and } | Curly Braces | -| < and > | Less Than and Greater than Signs | -| = | Equals Sign | -| / | Forward Slash | -| ! | Exclamation Mark | -| & | Ampersand | -| ~ | Tilde | -| | Space Character | - -You can also use additional padding characters if you want to break a number into groups. For example, to display a number as a phone number, you might use a mask like '00-0000-0000' or '(++00) 00-0000-0000'. - -It's a common practise in Accounting formats to wrap negative values in brackets; so you might use '([$€-nl-NL] #,##0.00)' for that section of the mask. - -To add words or for phrases to the mask, you should wrap the text in quotes: e.g. '#.00" Surplus";-#.00" Deficit";"Out of Stock"'. - -![Text String Example.png](images/Behind the Mask/Text String Example.png) - -### Indents, Spacing and Alignment - -If you're wrapping negative values in brackets, you might like like to align your positive values with your negative values on the decimal, then you need to apply indents to the positive values to match the width of the bracket characters. -The underscore code (`_`) tells Excel to pad the display to the width of the next character in the mask, so '_)' would tell Excel to pad to the width of ')' character like '[$€-nl-NL] _(#,##0.00_);[$€-nl-NL] (#,##0.00)'. - -![Indent.png](images/Behind the Mask/Indent.png) - -Accountants might also appreciate if the Currency symbols were also all aligned; so we can use the `*` code followed by a repeated character; and that will pad the width of the cell with the specified character. Typically, although not always, this will be a space character, '* '. - -![Padding.png](images/Behind the Mask/Padding.png) - -Which aligns all our currency symbols to the left of the cell, while displaying the value right-aligned in the cell, and all the decimal points neatly aligned. - -The `*` code can also be used to change the alignment of a value in a cell. If we want text to be rendered right aligned, even though the cell is left aligned, we can use '* @' as the mask, and this will push the display to the right of the cell. - -![Right Align.png](images/Behind the Mask/Right Align.png) - -Note that padding is not supported by PhpSpreadsheet's internal renderer for the cell's `getFormattedValue()` method, because the renderer is unaware of font or cell width, so it will simply add a single space in the formatted result. Nor will it change alignment in any way. - -### Colours - -You can use format masks to change the font colour for a certain value with a custom number format. -e.g. '[Red]@' - -Masking supports the following 8 main colours. - - - Black - - Red - - Green - - Blue - - Cyan - - Yellow - - Magenta - - White - -To specify the colour, just type one of those colour names in the appropriate section of your number format code, wrapped in square braces (e.g. '[red]'). -This colour code must be at the very start of the section, before any other formatting characters or instructions. -The colour name is case-insensitive. - -If we wanted to show positive values in green and negative values in red we could apply different colours to the different sections of the mask, e.g. "[Green]#,##0.00;[Red]#,##0.00;0.00". - -> **Warning**: Colour masking doesn't apply when using Excel's `TEXT()` function; only when it is applied to a Cell's Format Mask. - -### Conditional Formatting - -Not to be confused with actual Conditional Formatting in MS Excel; but we can apply some limited condition checks in normal Cell Format Masks, and apply different masking based on those conditions. - -While by default the different sections are interpreted by Excel as positive, negative, zero and text, we can override these definitions with conditions. -We do this by defining the condition for matching against the value inside square braces. - -![Conditional 1.png](images/Behind the Mask/Conditional 1.png) - -The mask that we're using here is `[Red][<65]"Fail";[Blue]"Pass"`. -This tells Excel to display the text "Fail" if the value in the Cell is less than 65, otherwise to display "Pass". - -The symbols allowed for comparison in Conditions are the standard mathematical comparison operators: - -| Symbol | Meaning | -|--------|-----------------------| -| \> | Greater than | -| \>= | Greater than or Equal | -| < | Less than | -| <= | Less than or Equal | -| = | Equal | -| <\> | Not Equal | - -In this next example, we've created an additional condition, so we have three sections in the mask: the "Pass" grade is now any student that hasn't failed, but whose score is less than 85; the last section awards a grade of "Distinction" to any student whose score doesn't match the criteria for "Pass" or "Fail" (i.e. exceeds 85). -`[Red][<65]"Fail";[Blue][<85]"Pass";"Distinction"` - -![Conditional 2.png](images/Behind the Mask/Conditional 2.png) - -We do need to be careful about the order that we define the conditions, because Excel will apply the mask for the first condition that matches the Cell value. - -> **Note**: Conditional Formatting using the Number Mask will also work with the TEXT() Function, although not with colour highlighting. - -We can also use Conditional Formatting to display Lakh, the different grouping often found in India and the countries of that region. -While the thousands separator normally represents grouping to powers of 3 (103, 106, 109, etc), the Lakh is 103, 105, 107, etc. and is written as `1,00,000`. -After the first 1000, the comma separator is used to represent groups of 2 digits, not groups of 3 digits. -150,000 rupees is 1.5 lakh rupees, and is written as `₹1,50,000` or `INR 1,50,000`. - -The mask used to represent lakh is: -[>=10000000][$₹]##\,##\,##\,##0;[>=100000][$₹]##\,##\,##0;[$₹]##,##0 - -Note that we're only using the `,` for thousands grouping in the final block, to represent values less than 100,000 where we would only display a single `,` as a thousands separator. -For the `,` in higher values, we are displaying a string literal `,` identified as such by the '\' immediately before it in the mask. - -## Building Composite Masks using PhpSpreadsheet's Wizards - -Even though PhpSpreadsheet's Wizards don't yet support building sections with different masks for positive, negative, zero, and text, you can still create these using the Wizards as building blocks. - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Currency Wizard to build the Format Mask -$currencyMask = new Currency( - '€', - 2, - Number::WITH_THOUSANDS_SEPARATOR, - Currency::TRAILING_SYMBOL, - Currency::SYMBOL_WITH_SPACING -); - -// Build the composite mask applying colours to the different sections -$compositeCurrencyMask = [ - '[Green]' . $currencyMask, - '[Red]' . $currencyMask, - $currencyMask, -]; - -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode(implode(';', $compositeCurrencyMask)); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->getFormatCode()); // [Green]#,##0.00 €;[Red]#,##0.00 €;#,##0.00 € -``` -We repeat the mask that's generated by the "Wizard" for each section of the composite mask, adding the required colour to each section. - -If we've used a locale to build a mask, then we may already have multiple sections: -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; - -// Set Cell value -$worksheet->getCell('C20')->setValue(-12345.67890); - -// Set Cell Style using the Currency Wizard to build the Format Mask -$currencyMask = new Currency( - '€', - locale: 'nl_NL' -); - -// Split the generated mask into sections -// This particular mask already has positive and negative value sections, -// but does not have a zero value section -// Other locales may only have a positive section; or may already have a zero section -$currencyMaskSections = explode(';', $currencyMask); -// Recreate the modified mask applying colours to the different sections -$compositeCurrencyMask = [ - '[Green]' . $currencyMaskSections[0], - '[Red]' . $currencyMaskSections[1] ?? $currencyMaskSections[0], - $currencyMaskSections[2] ?? $currencyMaskSections[0], -]; - -$worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - ->setFormatCode(implode(';', $compositeCurrencyMask)); - -var_dump($worksheet->getCell('C20') - ->getStyle()->getNumberFormat() - // [Green][$€-nl-NL] #,##0.00;[Red][$€-nl-NL] -#,##0.00;[$€-nl-NL] #,##0.00 - ->getFormatCode()); -``` -If the locale-generated mask already has a section defined, then we use that, otherwise we use the positive section (section 0) that will always exist as the base for each section. -> **Warning:** You might need to add an explicit `-` for the negative section if that needs to be created. - -## Summary - -Even though Excel displays the formatted value in the grid, the underlying value in the cell is unchanged. -The value being displayed as a date is still an Excel Serialized Timestamp, even though it is being displayed as '2023-02-28'; the student grade is still a number, even though it is being displayed as "Distinction"/"Pass"/"Fail"; and the cell that looks empty may not be as empty as you think. -The edit bar still shows us the value in the cell, not the formatted value; and we can still use that underlying value in formulae. - -![Summary - Still a numeric value.png](images/Behind the Mask/Summary - Still a numeric value.png) - -And we can even format the cell containing the result of that formula. - -Number format masks allow us to present the spreadsheet data in a format that makes it easy for the user to interpret; so they add a lot of value to the spreadsheets that we create. -We just need to understand how to use them well to unlock that value. diff --git a/docs/topics/Looping the Loop.md b/docs/topics/Looping the Loop.md deleted file mode 100644 index 09fefe67ff..0000000000 --- a/docs/topics/Looping the Loop.md +++ /dev/null @@ -1,501 +0,0 @@ -# Looping the Loop - -PhpSpreadsheet uses a lot of memory to maintain the Spreadsheet model; but I regularly see developers loading a Spreadsheet file and then calling the `toArray()` methods so that they can loop through the rows and columns of a worksheet. -PHP arrays are also notoriously memory-intensive, so creating a large array duplicating the data that is already in the Spreadsheet model is a very inefficient use of memory. -Generally, unless we are always working with very small spreadsheets, we would want to avoid this. - -So in this article, I'm going to look at a number of different ways of iterating through a worksheet to access the row and cell data; at their limitations; and at some of the options that each provides. - -## Using `toArray()` - -Using a sample data file from Microsoft and available at https://go.microsoft.com/fwlink/?LinkID=521962, I can load up the file, call `toArray()` to return the worksheet data in an array, and iterate over the rows and cells of that array with the following code. - -```php -$inputFileType = 'Xlsx'; -$inputFileName = __DIR__ . '/../Financial Sample.xlsx'; - -$reader = IOFactory::createReader($inputFileType); -$spreadsheet = $reader->load($inputFileName); -$worksheet = $spreadsheet->getActiveSheet(); - -$dataArray = $worksheet->toArray(); - -foreach ($dataArray as $row) { - foreach ($row as $cellValue) { - // Do something with the cell data here. - } -} -``` - -The Financial Sample spreadsheet is fairly small, 701 rows (including a heading row) and 16 columns; and is predominantly numeric data. -To simulate a larger worksheet, I've duplicated that data to give 7001 rows; but this is still a small worksheet as MS Excel xlsx files can contain 1 million rows in each of several worksheets. - -If we look at the timings and memory usage for this process with my extended MS Financial Sample spreadsheet: -``` -Current memory usage: 47104 KB - -Call time to build array was 0.6603 seconds - -Call time to iterate array rows was 0.0130 seconds -Current memory usage: 57344 KB - Peak memory usage: 57344 KB -``` -We can see that using `toArray()` increases memory usage by 10240KB (10MB): that is the memory used by the array for a relatively small worksheet (less than 120,000 cells). -For larger worksheets, with more rows and columns, and with more text than numeric values, this memory overhead can grow significantly larger. - -And while iteration over the array is very quick, it still takes 0.6603 seconds to build the array before we can start iterating over those rows and cells. - ---- - -The `toArray()` method is easy to use: but not only is it increasing the memory overhead, especially with larger worksheets; but it also lacks flexibility. -It provides limited control over how the data from each cell is returned in the array. -It can return the raw cell value (which isn't particularly useful if the cell contains a formula, or if the value should be interpreted as a date); it can force PhpSpreadsheet to calculate formulae and return the calculated value; or it can return the formatted cell value (which includes calculating any formulae) so that date values are presented in a human-readable format, but which will also format numeric values with thousand separators where the cell style applies that. - -| Argument Name | DataType | Default | Purpose | -|--------------------|----------|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| $nullValue | mixed | null | A value to be returned in the array if a cell doesn't exist. | -| $calculateFormulas | boolean | false | Flag to indicate if formula values should be calculated before returning. | -| $formatData | boolean | false | Flag to request that values should be formatting before returning. | -| $returnCellRef | boolean | false | False - Return a simple enumerated array of rows and columns (indexed by number counting from zero)
True - Return rows and columns indexed by their actual row and column IDs. | - -### Dealing with empty rows - -The example spreadsheet that I've used here is well behaved, with no empty rows. Empty rows can cause problems, even when working in Excel itself. - -Let's take a look at a worksheet of Sales Data, where we're missing the returns for a couple of months: - -![Empty Rows.png](images/Looping the Loop/Empty Rows.png) - -If we're using MS Excel, and we hit `Ctrl-T` to create a table from this data, we might expect Excel to build that table from all rows up to `Dec`; but it won't, it will only build the table up to the next empty row. - -![Table with Empty Rows.png](images/Looping the Loop/Table with Empty Rows.png) - -And unless we're careful, we might not even notice that the last few months of the year are omitted. -So empty rows can create problems even in MS Excel itself; and we certainly need to have some way of identifying them when we're processing a worksheet using PhpSpreadsheet. - ---- - -While we're iterating through a spreadsheet with PhpSpreadsheet, we might want to avoid trying to process blank data if we reach a row that is empty; or we might want to terminate iterating when we encounter an empty row. - -If we've created an array from a worksheet, then an empty row will be a row where every cell/column entry has a null value (unless called specifying an alternative value using the `$nullValue` argument). - -We can filter the row to eliminate null values, then count the length of that filtered array: if there are no remaining cells, then the row is empty. We can then skip that row in our code using `continue`. - -```php -foreach ($dataArray as $row) { - // Check for empty rows - if (count(array_filter($row, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - foreach ($row as $cellValue) { - // Do something with the cell data here. - } -} -``` - -Or if we want to terminate iterating when we encounter an empty row, use `break` rather than `continue`. - -```php -foreach ($dataArray as $row) { - // Check for empty rows - if (count(array_filter($row, function ($value) { - return $value !== null; - })) === 0) { - break; // Stop at the first empty row - } - - foreach ($row as $cellValue) { - // Do something with the cell data here. - } -} -``` - -Using `toArray()` won't change anything in the worksheet model: it won't modify values or create new cells. -It will return a row/column entry for every cell that can exist, even if that cell doesn't exist in the worksheet, or is part of a merge range. -> **Note**: It is possible for several cells in a merge range to have a value. Although MS Excel doesn't allow you to set data like this, the option is available in other Spreadsheet software, and if the file is saved as an xlsx file, then the data for those cells is retained in the file, even though only the top left cell of a merge range shows a value in MS Excel. In PhpSpreadsheet, accessing those cells (including using `toArray()`) will return the "hidden" value. - -One useful factor about returning an array of arrays is if we want to populate a data model from that row before persisting to a database, for example. We don't need to iterate the columns in that row, but can work directly with the column array for each row. - -```php -class MonthlySales { - private function __construct( - public readonly string $month, - public readonly array $sales, - ) {} - - public static function fromExcel(array $values, array $headers): self { - $month = array_shift($values); - return new self($month, array_combine($headers, $values)); - } -} - -$monthlySalesData = new MonthlySalesCollection(); - -// Read from the header row of the worksheet -$excelHeaderRow = ['Jones', 'Sorvino', 'Gupta', 'Choi']; - -$dataArray = $worksheet->toArray(formatData: true); -foreach ($dataArray as $excelDataRow) { - // Check for empty rows - if (count(array_filter($excelDataRow, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - $monthlySalesData->add(MonthlySales::fromExcel( - $excelDataRow, - $excelHeaderRow - )); -} -``` -We can pass the row array directly to the static `MonthlySales::fromExcel()` constructor for our data object, handling any validation and manipulation of the structure there, to map the Excel data row to that object properties, handling filtering within the business logic of the Monthly Sales object's static constructor. - ---- - -And remember that by default, `toArray()` returns a simple enumerated array of enumerated arrays, to reflect rows and columns. You can modify this using the `$returnCellRef` argument to the method: set `$returnCellRef` to true, and the array indexes will be the row number (with 1 as the first row) and the column address ('A', 'B', 'C', etc); which can be useful if you want to do some processing of the cells based on that column address. - -```php -class MonthlySales { - private function __construct( - public readonly string $month, - public readonly array $sales, - ) {} - - public static function fromExcel(array $values, array $headers): self { - $month = array_shift($values); - $salesValues = []; - foreach ($values as $column => $value) { - // Ignore salespeople who have null sales values - if ($value !== null) { - $salesValues[$headers[$column]] = $value; - } - } - return new self($month, $salesValues); - } -} - -$monthlySalesData = new MonthlySalesCollection(); - -// Read from the header row of the worksheet -$excelHeaderRow = [ - 'B' => 'Jones', - 'C' => 'Sorvino', - 'D' => 'Gupta', - 'E' => 'Choi' -]; - -$dataArray = $worksheet->toArray(formatData: true, returnCellRef: true); -foreach ($dataArray as $excelDataRow) { - // Check for empty rows - if (count(array_filter($excelDataRow, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - $monthlySalesData->add(MonthlySales::fromExcel( - $excelDataRow, - $excelHeaderRow - )); -} -``` - -## Using `rangeToArray()` - -The `toArray()` method uses information from the loaded file to identify the range of rows and columns to populate the array. -`toArray()` uses two cached values to identify the range of cells to populate the array, values that are returned by the `getHighestRow()` and `getHighestColumn()` methods. - -But many worksheets do have trailing empty rows (or columns); and it is quite common for an Excel spreadsheet to have only a few rows or columns of data, but for the spreadsheet itself to claim that the highest row is 1,048,576 or that the highest column is XFD. -Features such as Data Validation or Conditional Formatting that can also artificially inflate/increase the values returned by `getHighestRow()` and `getHighestColumn()` methods. - -If we use `toArray()` to build an array from the worksheet in this case, then it will build a 1,048,576x16,384 array, filled with null values, that will almost certainly exceed PHP's memory limits, and take a long time to do so. -And if we do have enough memory to build the array, we will still be iterating over a lot more array entries than we want. Even if we're skipping empty rows, we're still testing every row to see if it's empty. -Where possible, it's better to specify the limit of rows and columns that we want to use to build an array, and PhpSpreadsheet provides the `rangeToArray()` for that purpose. - -One option to reduce a large array using a lot of PHP memory would be to run a loop using `rangeToArray()` to build smaller arrays for blocks of perhaps 100 rows at a time. -This will still take a while to run if we have a lot of trailing empty rows, but it won't exceed PHP's memory limits. - -```php -$startRow = 1; -$batchSize = 100; -while ($startRow <= $maxRow) { - $endRow = min($startRow + $batchSize, $maxRow); - $dataArray = $worksheet->rangeToArray("A{$startRow}:{$maxColumn}{$endRow}"); - $startRow += $batchSize; - - foreach ($dataArray as $row) { - // Check for empty rows - if (count(array_filter($row, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - foreach ($row as $cellValue) { - // Do something with the cell data here. - } - } -} -``` - -Alternatively, we can identify the highest row and highest column that actually contain cell data using the `getHighestDataRow()` and `getHighestDataColumn()` methods. This allows us to specify a range to pass to the `rangeToArray()` method. - -```php -$maxDataRow = $worksheet->getHighestDataRow(); -$maxDataColumn = $worksheet->getHighestDataColumn(); - -$dataArray = $worksheet->rangeToArray("A1:{$maxDataColumn}{$maxDataRow}"); - -foreach ($dataArray as $row) { - // Check for empty rows - if (count(array_filter($row, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - foreach ($row as $cellValue) { - // Do something with the cell data here. - } -} -``` - -There might still be some empty rows in this array, so we still want to test for empty rows; but we won't have any trailing empty rows at the end of our data, so the iteration will terminate at the end of our specified row range, when we know we have no further data. - -And if there is a row or two of column headers that we want to ignore, we can modify the specified range to exclude them by adjusting the starting row of the range (e.g. `"A3:{$maxDataColumn}{$maxDataRow}"`); - -Because we're only building the array for a specified range of rows and columns, the array that the method builds will often be smaller than the array created by `toArray()`, using less memory; and it will often be faster iterating just the subset of rows that we've requested. - - -A combination of these approaches - batching and using the 'getHighestDataRow()' value, will be more memory-efficient, and possibly faster, than using 'toArray()'. -```php -$startRow = 1; -$batchSize = 100; -while ($startRow <= $maxDataRow) { - $endRow = min($startRow + $batchSize, $maxDataRow); - $dataArray = $worksheet->rangeToArray("A{$startRow}:{$maxDataColumn}{$endRow}"); - $startRow += $batchSize; - - foreach ($dataArray as $row) { - // Check for empty rows - if (count(array_filter($row, function ($value) { - return $value !== null; - })) === 0) { - continue; // Ignore empty rows - } - - foreach ($row as $cellValue) { - // Do something with the cell data here. - } - } -} -``` -How does this approach compare with using 'toArray()' in terms of memory and speed? Here are the details for using `rangeToArray()` with a batched approach: -``` -Current memory usage: 47104 KB - -Call time to batch iterate array rows was 0.6844 seconds - Current memory usage: 47104 KB - Peak memory usage: 49152 KB -``` -While the total time is 0.6844 seconds, that included building the smaller batched arrays, so its speed is comparable to the total time of 0.6733 seconds using `toArray()`. -But a peak memory usage of 49,152KB compared with the 57,344KB used by `toArray()` make this approach a lot more memory efficient. - -Like `toArray()`, `rangeToArray()` is easy to use, but it has the same limitations for flexibility. It provides the same limited control over how the data from each cell is returned in the array as `toArray()`. -The same additional arguments that can be provided for the `toArray()` method can also be provided to `rangeToArray()`. - - -## Using `rangeToArrayYieldRows()` - -Since v2.1.0 the worksheet method `rangeToArrayYieldRows()` is available. -It allows you to iterate over all sheet's rows with little memory consumption, -while obtaining each row as an array: - -```php -$rowGenerator = $sheet->rangeToArrayYieldRows( - 'A1:' . $sheet->getHighestDataColumn() . $sheet->getHighestDataRow(), - null, - false, - false -); -foreach ($rowGenerator as $row) { - echo $row[0] . ' | ' . $row[1] . "\n"; -} -``` - -See `samples/Reader2/23_iterateRowsYield.php`. - - -## Using Iterators - -You don't need to build an array from the worksheet to loop through the rows and columns and do whatever processing you need; you can loop through the rows and columns in the Worksheet directly and more efficiently using PhpSpreadsheet's built-in iterators. - -And this also gives a lot more flexibility in how you can present the cell values, because the iterator will return the Cell itself, not a representation of its value. You can read its value, check its style, identify if it is part of a merge range. - -```php -$rowIterator = $worksheet->getRowIterator(); -foreach ($rowIterator as $row) { - $columnIterator = $row->getCellIterator(); - foreach ($columnIterator as $cell) { - // Do something with the cell here. - } -} -``` - -Let's look at the memory usage and timings for using PhpSpreadsheet's Iterators, as we did for building and iterating through the array. - -``` -Current memory usage: 47104 KB - -Call time to iterate rows was 0.0930 seconds - Current memory usage: 47104 KB - Peak memory usage: 47104 KB -``` - -Using the PhpSpreadsheet Iterators isn't as fast as iterating over an array; but it doesn't have the time or memory overheads of actually building that array from the worksheet. -Using the same example spreadsheet, it only took 0.0130 seconds to iterate every cell of that array, but 0.6603 seconds to build the array, a total of 0.6733 seconds; but using the Iterator has performed the equivalent task in just 0.0930 seconds; about 7 times faster and without the increased memory overhead of the array. - -### Dealing with empty rows - -As, when we were iterating over the array, we might want to identify empty rows so that we can avoid trying to process them. The Row Iterator provides a method to identify empty rows. - -```php -$rowIterator = $worksheet->getRowIterator(); -foreach ($rowIterator as $row) { - if ($row->isEmpty()) { // Ignore empty rows - continue; - } - - $columnIterator = $row->getCellIterator(); - foreach ($columnIterator as $cell) { - // Do something with the cell here. - } -} -``` - -One additional feature when using the Iterator to determine whether a row is empty or not is that we can set our own rules to define "empty". -The default rule is if there is no entry for the Cell in the Cell Collection. -If we also want to skip any Cell that contains a null value, then we can pass an argument using the pre-defined constant `CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL`. -If we also want to skip any Cell that contains an empty string, then we can pass an argument using the pre-defined constant `CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL`. - -And we can combine those rules: -```php -if ($row->isEmpty( - CellIterator::TREAT_EMPTY_STRING_AS_EMPTY_CELL | - CellIterator::TREAT_NULL_VALUE_AS_EMPTY_CELL) - ) { // Ignore empty rows - continue; -} -``` - -Since PhpSpreadsheet 1.27.0, we can take this empty test one step further. -If we look at a slightly modified version of the Sales Data worksheet, rows 7 and 10 have no sales data, but they aren't empty because there is a month value in column A. - -![Empty Rows 2.png](images/Looping the Loop/Empty Rows 2.png) - -But we can tell the `isEmpty()` method to only check if a specified range of columns is empty in a row. - -```php -if ($row->isEmpty(startColumn: 'B', endColumn: 'E') { - // Ignore empty rows where columns B to E are empty values - // even though there is a value in Column A. - continue; -} -``` - ---- - -Like `toArray()`, the Iterators use the `getHighestRow()` and `getHighestColumn()` methods to identify the maximum row and column values for iterating; so it can still iterate over a lot of trailing empty rows and columns. -But that is just a default behaviour. -Similarly to `rangeToArray()` we can specify a range of rows, and a range of columns to iterate. - -```php -$maxDataRow = $worksheet->getHighestDataRow(); -$maxDataColumn = $worksheet->getHighestDataColumn(); - -$rowIterator = $worksheet->getRowIterator(1, $maxDataRow); -foreach ($rowIterator as $row) { - if ($row->isEmpty()) { // Ignore empty rows - continue; - } - - $columnIterator = $row->getCellIterator('A', $maxDataColumn); - foreach ($columnIterator as $cell) { - // Do something with the cell here. - } -} -``` - -and if we have heading rows at the top of the worksheet that we want to ignore: -```php -$rowIterator = $worksheet->getRowIterator(3, $maxDataRow); -``` - -And if we want to return only cells that aren't empty in the row, then we can tell the Cell Iterator to skip empty cells. - -```php -$rowIterator = $worksheet->getRowIterator(1, $maxDataRow); -foreach ($rowIterator as $row) { - $columnIterator = $row->getCellIterator(); - $columnIterator->setIterateOnlyExistingCells(true); - foreach ($columnIterator as $cell) { - // Do something with the cell here. - } -} -``` - -Alongside the speed and memory benefits, another big advantage of using the Iterators (Row and Cell, or Column and Cell) is that we get direct access to the cell itself. We can look at its value, its style; we can identify if it is a formula, or formatted as a date/time, whether it is part of a merge range: we can choose exactly what we want to do with it. - ---- - -One drawback of the Cell Iterator is that it will create a new cell if none exists (by default) unless we're skipping empty cells. -Until PhpSpreadsheet 1.27.0, the Cell Iterator would always create a new Cell if one didn't exist in the Cell Collection when it was required to access it. And this can lead to increasing memory consumption. - -PhpSpreadsheet 1.27.0 introduced the option to return a null value rather than to create and return a new Cell. - -```php -$rowIterator = $worksheet->getRowIterator(1, $maxDataRow); -foreach ($rowIterator as $row) { - $columnIterator = $row->getCellIterator(); - $columnIterator->setIfNotExists(CellIterator::IF_NOT_EXISTS_RETURN_NULL); - foreach ($columnIterator as $cell) { - if ($cell !== null) { - // Do something with the cell here. - } - } -} -``` - -The default Iterator behaviour is still to create a new Cell, to retain backward compatibility; but the option to return a null value instead of a new empty cell now exists. -> **Note**: This default behaviour is likely to be reversed with the eventual release of PhpSpreadsheet 2.0, with a null value as the default return, but with the option to create a new empty cell. - -## Summary of Performance and Benefits - -So here is a quick summary of timing and memory usage for the three different approaches to iterating through the rows and cells of the 7000 row sample worksheet. - -Memory usage is adjusted for the 47,104 KB baseline of the loaded file. - -| Approach | Total Time (s) | Memory (KB) | -|------------------------|----------------|-------------| -| toArray() | 0.6733 | 10,240 | -| rangeToArray (Batched) | 0.6844 | 2,048 | -| Iterators | 0.0930 | 0 | - -These figures are all based on a well-formed spreadsheet, with no trailing empty rows, or empty rows within the dataset. -Empty rows within a dataset can be identified by all three approaches, although only Iterators have a built-in method to identify an empty row. - -Using `toArray()` is not good for controlling memory usage, especially if there are trailing empty rows, so it should generally be avoided; but both `rangeToArray()` and the Iterators can exclude trailing rows by setting their scope based on the `getHighestDataRow()` and `getHighestDataColumn()` values. - -Batching rows with `rangeToArray()` is useful for keeping memory usage under control if you want to work with arrays. - -But using the Iterators is significantly faster than either "array" approach, with no memory overhead (especially if using the option of a null return for Cells that don't exist that was made available in PhpSpreadsheet 1.27.0); and as the Iterators return the Cell object rather than simply a cell value, they provide a lot more flexibility in how to process that cell. -The flexibility to configure the definition of an empty row may also be useful to developers using this approach to iterating through a worksheet. - -## Conclusions - -While it might require a little more userland code by developers using PhpSpreadsheet; because they are faster, have no additional memory overhead, and provide more flexibility, Iterators are the recommended approach for looping through the rows (and cells) of a worksheet. - diff --git a/docs/topics/The Dating Game.md b/docs/topics/The Dating Game.md deleted file mode 100644 index 5b0c2812ff..0000000000 --- a/docs/topics/The Dating Game.md +++ /dev/null @@ -1,303 +0,0 @@ -# The Dating Game - -Date and Time values are stored in different ways in spreadsheet files, depending on the file format; but internally when working in Excel the cell always contains a numeric value, representing the number of days since a baseline date, and formatted to appear as a human-readable date using a "Number Format Mask". This number is sometimes referred to as a serialized Excel date or timestamp. - -## Dates - -That baseline date is normally 1st January 1900, although it can be 1st January 1904 (if the original spreadsheet file was created using the Mac version of MS Excel). Excel maintains a flag in the file indicating which baseline should be used; for file formats that don't provide this flag (such as .slk or .csv), the calendar defaults to the 1900 baseline. -![Date as a number.png](images/The Dating Game/Date as a number.png) - -Note that the baseline date itself is day 1; so strictly speaking, the base date 0 is '1899-12-31': Excel considers any value between 0 and 1 as purely a time value, trying to display 0 using a date format mask like 'yyyy-mm-dd' will show an invalid date like '1900-01-00' rather than '1899-12-31', but when using a time format mask like 'hh:mm:ss' it will appear as '00:00:00' (midnight). Values less than 0 are invalid as dates or as times, so a negative value in a cell with a date "Number Format Mask" will display as '############' in Excel. - -Open/Libre Office and Gnumeric don't have this limitation, and negative date/timestamp values are recognised and formatted correctly; but it is recommended that you don't rely on this when working with PhpSpreadsheet. - -To write a date in a cell using PhpSpreadsheet, we need to calculate the serialized Excel datestamp for that date. Methods to do this are available in the Shared\Date class, which provides a number of methods for conversion between different date options typically used in PHP applications (Unix timestamp, PHP DateTime objects and some recognisable formatted strings) and the Excel serialized value; and vice versa. - - - Shared\Date::convertIsoDate() - - Converts a date/time in [ISO-8601 standard format](https://en.wikipedia.org/wiki/ISO_8601) to an Excel serialized timestamp - - Shared\Date::PHPToExcel() - - Converts a Unix timestamp, a PHP DateTime object, or a recognisable formatted string to an Excel serialized timestamp - - Shared\Date::dateTimeToExcel() - - Converts a Unix timestamp to an Excel serialized timestamp - - Shared\Date::timestampToExcel() - - Converts a PHP DateTime object to an Excel serialized timestamp - - Shared\Date::formattedPHPToExcel() - - Converts year, month, day, hour, minute, and second to an Excel serialized timestamp - - Shared\Date::excelToDateTimeObject() - - Converts an Excel serialized timestamp to a PHP DateTime object - - Shared\Date::excelToTimestamp() - - Converts an Excel serialized timestamp to a Unix timestamp. - - The use of Unix timestamps, and therefore this function, is discouraged: they are not Y2038-safe on a 32-bit system, and have no timezone info. - -We probably also want to set the number format mask for the cell so that it will be displayed as a human-readable date. -```php -use PhpOffice\PhpSpreadsheet\Spreadsheet; -use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDate; - -// Create new Spreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Calculate today's date as an Excel serialized timestamp -$today = SharedDate::PHPToExcel(new DateTime('today')); - -$data = [ - ['Formatted Date', 'Numeric Value'], - ['=C2', 1], - ['=C3', 2], - ['=C4', $today], -]; - -// Write our data to the worksheet -$worksheet->fromArray($data, null, 'B1'); - -// Display values in column B as human-readable dates -$worksheet->getStyle('B2:B4')->getNumberFormat()->setFormatCode('yyyy-mm-dd'); -// Set some additional styling -$worksheet->getStyle('B1:C1')->getFont()->setBold(true); -$worksheet->getColumnDimension('B')->setAutoSize(true); -``` - -## Times - -Dates are always the integer part of the value (1, 2, 44943): the fractional part of the value is used to represent the time as a fraction of the day. So a value of 0.5 is 12:00 midday; 0.25 is 06:00 in the morning and 0.75 is 18:00 in the evening. -![Time as a number.png](images/The Dating Game/Time as a number.png) - -A float value greater than 1, like 44943.5 is considered as a datetime value: 12:00 (midday) on the 17th of January 2023. - -As with dates, to write a time value to a cell in PhpSpreadsheet, we write the numeric value for that time (or date/time) to the cell, and then apply a number format mask to the cell so that it will be displayed in a human-readable format. -```php -use PhpOffice\PhpSpreadsheet\Spreadsheet; -use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDate; - -// Create new Spreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Calculate today's date as an Excel serialized timestamp -$today = SharedDate::PHPToExcel(new DateTime('today')); - -$data = [ - ['Formatted Time', 'Numeric Value'], - ['=C2', 0], - ['=C3', 0.25], - ['=C4', 0.5], - ['=C5', 0.75], - ['=C6', $today + 0.5], -]; - -// Write our data to the worksheet -$worksheet->fromArray($data, null, 'B1', true); - -// Display values in column B as human-readable dates -$worksheet->getStyle('B2:B5')->getNumberFormat()->setFormatCode('hh:mm:ss'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('yyyy-mm-dd hh:mm:ss'); -// Set some additional styling -$worksheet->getStyle('B1:C1')->getFont()->setBold(true); -$worksheet->getColumnDimension('B')->setAutoSize(true); -``` - -The same `Shared\Date` functions that convert between Excel dates and Unix Timestamps or PHP DateTime objects can also be used to convert time values. - -## Dates/Times and Value Binders - -It is a standing joke that MS Excel tries to identify date and time values as you are entering data in Excel, and often treats any value as a possible date, converting it to an Excel serialized timestamp and applying date/time formatting, even though that may not have been what was intended. -![StringDateValues.jpg](images/The Dating Game/StringDateValues.jpg) - -Any change to a cell value in PhpSpreadsheet that isn't made using the setCellValueExplicit() method is passed through a "Value Binder", which triggers additional settings for that cell. - -> **Note**: dates and times maintained in true spreadsheet format files are always correctly identified in the file, and setCellValueExplicit() is used to store those values, with the formatting mask defined in that file. However, non-spreadsheet files such as .csv don't identify dates/times, so the Value Binder behaviour applies when loading those files. - - -The Default Value Binder attempts to identify the datatype of the value and sets the cell datatype accordingly: and if you pass a string value like '2023-01-18 12:15:00' then the Default Value Binder will simply treat it as a string, and set it accordingly. - -However, if you choose to use the Advanced Value Binder, then that contains logic which looks more closely at those string values, and tries to determine if they are likely to be formatted dates or times, and in that regard it emulates Excel's behaviour. If the string value looks like a date or time, then it is converted to a serialized Excel date/timestamp, and an appropriate format mask is set for that cell. - -While the logic of this isn't perfect, I'd like to believe that it is less error-prone than Excel's own logic; but it won't necessarily recognise ambiguous formats and values correctly like '1/7/2023' as dates. (Is that the 1st of July? Or the 7th of January?) - -## Reading Dates and Times from cells - -When we read the value of a cell that contains a Date/Time value, we are only reading a number (the Excel serialized timestamp); it is only the Number Format Mask that allows us to say whether that number is simply a number, or is meant to be a Date/Time value. - -PhpSpreadsheet provides a number of methods to identify whether a Number Format Mask represents a Date/Time format mask, or whether a Cell is formatted as a Date/Time. - -- Shared\Date::isDateTimeFormat() - - Identifies if a NumberFormat Style object is an Excel Date/Time style format mask. -- Shared\Date::isDateTimeFormatCode() - - Identifies if the string value of a Number Format mask is an Excel Date/Time style format mask. -- Shared\Date::isDateTime() - - Identifies if a Cell is styled with a Number Format mask is an Excel Date/Time style format mask.**** - -These functions allow you to identify whether a cell value should be converted to a Unix Timestamp or PHP DateTime object (using one of the conversion functions provided in `Shared\Date`) for processing in your script, or for formatting as a Date/Time value. - -## Date Arithmetic - -Because dates and times are just numeric values in MS Excel, this makes date/time arithmetic very easy to calculate: to count the number of days (or a duration) between two dates, we can use a simple subtraction. -![Date Arithmetic.png](images/The Dating Game/Date Arithmetic.png) - -Similarly, we can add date/time values like adding a duration to a start date to calculate an end date. -![Date Arithmetic 2.png](images/The Dating Game/Date Arithmetic 2.png) - -## Excel Date Functions - -MS Excel provides a number of functions that will return a date or a time value. It also recognises when one of these functions is the "outer" function in a formula, so the final result will always be a serialized date/time value, and sets an appropriate format mask for that value. - -This behaviour is not replicated in PhpSpreadsheet. If you set a formula for a cell through your code that will return a date or time value, then you will also need to set the format mask for that cell manually. - -## Formatting Options - -PhpSpreadsheet provides a number of built-in format code constants for dates and times in the NumberFormat class, matching those defined in the OfficeOpenXML specification, but you can always just set the format to any valid Excel formatting string, the equivalent of setting a custom date format in Excel. - -### Dates - -When setting up a custom date format in Excel, you can use the following codes. - -| Code | Description | Example (January 3, 2023) | -|-------|-------------------------------------|---------------------------------------| -| m | Month number without a leading zero | 1 | -| mm | Month number with a leading zero | 01 | -| mmm | Month name, short form | Jan | -| mmmm | Month name, full form | January | -| mmmmm | Month as the first letter | J (stands for January, June and July) | -| d | Day number without a leading zero | 3 | -| dd | Day number with a leading zero | 03 | -| ddd | Day of the week, short form | Tue | -| dddd | Day of the week, full form | Tuesday | -| yy | Year (last 2 digits) | 23 | -| yyyy | Year (4 digits) | 2023 | - -### Times - -When setting up a custom time format in Excel, you can use the following codes. - -| Code | Description | Displays as | -|--------|--------------------------------------------------------------------|-------------| -| h | Hours without a leading zero | 0-23 | -| hh | Hours with a leading zero | 00-23 | -| m | Minutes without a leading zero | 0-59 | -| mm | Minutes with a leading zero | 00-59 | -| s | Seconds without a leading zero | 0-59 | -| ss | Seconds with a leading zero | 00-59 | -| AM/PM | Periods of the day
(if omitted, 24-hour time format is used) | AM or PM | -> **Warning** -MS Excel allows any separator character between hours/minutes/seconds; PhpSpreadsheet currently requires a colon (`:`) to correctly distinguish minutes from months when rendering a time format within PHP code, although it will correctly write the format to file if any other separator character is used. - -### Duration (Elapsed Time) - -Excel also supports formatting a value as a duration; a total number of hours, minutes or seconds rather than a time of day. - -| Code | Description | Displays as | -|---------|----------------------------------------------------------------|-------------| -| [h]:mm | Elapsed time in hours | e.g. 25:02 | -| [hh]:mm | Elapsed time in hours
with a leading zero if less than 10 | e.g. 05:02 | -| [mm]:ss | Elapsed time in minutes | e.g. 63:46 | -| [m]:ss | Elapsed time in minutes
with a leading zero if less than 10 | e.g. 03:46 | -| [s] | Elapsed time in seconds | | -| [ss] | Elapsed time in seconds
with a leading zero if less than 10 | | - -If you want to display an elapsed time in days, then you can use a normal date mask like `d h:mm` (without month or year), with the limitation that it will not exceed 31 days. - -### Localisation - -#### Built-in Formats - -Some of the Excel built-in format masks are locale-aware. -![Locale.png](images/The Dating Game/Locale.png) - -Those locale-aware formats are highlighted with a * in Excel's drop-down lists for Date and Time, and will adapt when viewed in MS Excel, based on the locale settings of that local PC. - -PhpSpreadsheet is not locale-aware, so it will not render these formats as locale-formats, just as generic Date/Time formats; and localisation will be not be saved when writing to a spreadsheet file. - -#### Custom Formats - -When you're displaying a date/time using a format mask that isn't locale-aware in MS Excel, the locale settings for Excel are applied. So if you're displaying a month or day name, these will appear in the appropriate language for the locale of your PC. -![Locale1.png](images/The Dating Game/Locale1.png) - -You can force the display for a specific locale by prefixing the format mask with a locale setting, so that Excel will render it using the appropriate language. The locale code should be enclosed in [square brackets] and preceded with the dollar sign ($) and a dash (-). - -In this example, I'm forcing Dutch Netherlands by prefixing the mask with `[$-nl-NL]`. As an alternative, I could also have used the Windows LCID for that locale (`[$-413]`). -![Locale2.png](images/The Dating Game/Locale2.png) - -Because PhpSpreadsheet is not locale-aware, displaying the formatted value for that cell in your PHP script won't show the locale date/time, only a generic date/time; but it will still be written correctly when the file is saved (as a spreadsheet format) for Excel to render correctly and in the appropriate language. - -If you need this, then you can find a list of Windows LCID values [here](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/a29e5c28-9fb9-4c49-8e43-4b9b8e733a05) - -## Summary Example - -Let's summarise some of this information with a script that will build a project timesheet for a week of work on that project. - -I'll keep the basic data in arrays for simplicity. -```php -// In a real application, we might read this data from a database to build a project timesheet -$projectHeading = [['Project', 'PhpSpreadsheet - The Dating Game']]; -$weekHeading = [ - ['Week', '=ISOWEEKNUM(D3)', 'Start Date', '=DATE(2023,1,16)'], - ['Day', 'Start Time', 'End Time', 'Hours Worked'], -]; - -$timesheetData = [ - ['2023-01-16', '17:25', '20:15'], - ['2023-01-16', '20:50', '23:35'], - ['2023-01-17', '18:10', '19:35'], - ['2023-01-17', '20:10', '22:15'], - ['2023-01-17', '22:35', '23:45'], - ['2023-01-18', '09:15', '11:25'], -]; -``` -Because I've used string values for the dates and times, I'm going to use the Advanced Value Binder to populate the worksheet. -The Binder will also format the time values in columns B and C; but I want to override the Binder formatting for date values in column A; and I'm using an Excel formula for the "start date" value in cell D3, so I have to set the format manually for that. -```php -use PhpOffice\PhpSpreadsheet\Spreadsheet; -use PhpOffice\PhpSpreadsheet\Cell\Cell; -use PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder; -use PhpOffice\PhpSpreadsheet\Style\Alignment; - -// Create new Spreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); -// Use the Advanced Value Binder so that our string date/time values will be automatically converted -// to Excel serialized date/timestamps -// Old method using static property -Cell::setValueBinder(new AdvancedValueBinder()); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet->setValueBinder(new AdvancedValueBinder()); - -// Write our data to the worksheet -$worksheet->fromArray($projectHeading); -$worksheet->fromArray($weekHeading, null, 'A3'); - -// Let Excel calculate the duration for each timesheet entry -$row = 4; -foreach ($timesheetData as $timesheetEntry) { - ++$row; - $worksheet->fromArray($timesheetEntry, null, "A{$row}"); - $worksheet->setCellValue("D{$row}", "=C{$row} - B{$row}"); -} -$totalRow = $row + 2; -$worksheet->setCellValue("D{$totalRow}", "=SUM(D4:D{$row})"); -$worksheet->setCellValue("E{$totalRow}", 'Total Hours'); -``` -And then the final formatting: -```php -// Display values in column A as human-readable dates -$worksheet->getStyle("A5:A{$row}")->getNumberFormat()->setFormatCode('dd (ddd)'); -// Display values in column D as human-readable durations -$worksheet->getStyle("D5:D{$totalRow}")->getNumberFormat()->setFormatCode('[h]:mm'); - -// Set some additional styling -$worksheet->getStyle('D3')->getNumberFormat()->setFormatCode('yyyy-mm-dd'); -$worksheet->getStyle('A1')->getFont()->setBold(true); -$worksheet->getStyle('A3:D4')->getFont()->setBold(true); -$worksheet->getStyle("A5:A{$row}")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); -$worksheet->getColumnDimension('D')->setAutoSize(true); -$worksheet->getStyle("E{$totalRow}")->getFont()->setBold(true); -``` - -And the resulting spreadsheet will look something like: -![Timesheet.png](images/The Dating Game/Timesheet.png) - -## Final Notes - -MS Excel is not Timezone aware, nor does it have any logic for handling Daylight Savings. - -Excel functions like the NOW() function return the serialized timestamp of the current date and time. The date and time are provided by the operating system, and that determines, according to the time zone and date of the year if Daylight Saving Time is in effect. So functions like NOW() include any DST offset, because it is automatically included by the OS. diff --git a/docs/topics/accessing-cells.md b/docs/topics/accessing-cells.md index a9fe3695de..f14e2bde46 100644 --- a/docs/topics/accessing-cells.md +++ b/docs/topics/accessing-cells.md @@ -2,24 +2,21 @@ Accessing cells in a Spreadsheet should be pretty straightforward. This topic lists some of the options to access a cell. -For all of these, the cell can be accessed by coordinate (e.g. `B3`), -by an array of column index (where A is 1) and row (e.g. `[2, 3]`), -or as a CellAddress object (e.g. `new CellAddress('B3', /* optional */ $worksheet)`. -## Setting a cell value +## Setting a cell value by coordinate -Setting a cell value can be done using the worksheet's +Setting a cell value by coordinate can be done using the worksheet's `setCellValue()` method. -```php +``` php // Set cell A1 with a string value $spreadsheet->getActiveSheet()->setCellValue('A1', 'PhpSpreadsheet'); // Set cell A2 with a numeric value -$spreadsheet->getActiveSheet()->setCellValue([1, 2], 12345.6789); +$spreadsheet->getActiveSheet()->setCellValue('A2', 12345.6789); // Set cell A3 with a boolean value -$spreadsheet->getActiveSheet()->setCellValue(new CellAddress('A3'), TRUE); +$spreadsheet->getActiveSheet()->setCellValue('A3', TRUE); // Set cell A4 with a formula $spreadsheet->getActiveSheet()->setCellValue( @@ -31,66 +28,12 @@ $spreadsheet->getActiveSheet()->setCellValue( Alternatively, you can retrieve the cell object, and then call the cell’s `setValue()` method: -```php +``` php $spreadsheet->getActiveSheet() ->getCell('B8') ->setValue('Some value'); ``` -### Creating a new Cell - -If you make a call to `getCell()`, and the cell doesn't already exist, then -PhpSpreadsheet will create that cell for you. - -### BEWARE: Cells and Styles assigned to variables as a Detached Reference - -As an "in-memory" model, PHPSpreadsheet can be very demanding of memory, -particularly when working with large spreadsheets. One technique used to -reduce this memory overhead is cell caching, so cells are actually -maintained in a collection that may or may not be held in memory while you -are working with the spreadsheet. Because of this, a call to `getCell()` -(or any similar method) returns the cell data, and sets a cell pointer to that cell in the collection. -While this is not normally an issue, it can become significant -if you assign the result of a call to `getCell()` to a variable. Any -subsequent calls to retrieve other cells will change that pointer, although -the cell object will still retain its data values. -This is also true when assigning a variable to the result of `getStyle()`. - -What does this mean? Consider the following code: - -```php -$spreadSheet = new Spreadsheet(); -$workSheet = $spreadSheet->getActiveSheet(); - -// Set details for the formula that we want to evaluate, together with any data on which it depends -$workSheet->fromArray( - [1, 2, 3], - null, - 'A1' -); - -$cellC1 = $workSheet->getCell('C1'); -echo 'Value: ', $cellC1->getValue(), '; Address: ', $cellC1->getCoordinate(), PHP_EOL; - -$cellA1 = $workSheet->getCell('A1'); -echo 'Value: ', $cellA1->getValue(), '; Address: ', $cellA1->getCoordinate(), PHP_EOL; - -echo 'Value: ', $cellC1->getValue(), '; Address: ', $cellC1->getCoordinate(), PHP_EOL; -``` - -The call to `getCell('C1')` returns the cell at `C1` containing its value (`3`), -together with its link to the collection (used to identify its -address/coordinate `C1`). The subsequent call to access cell `A1` -modifies the value of `$cellC1`, detaching its link to the collection. - -So when we try to display the value and address a second time, we can display -its value, but trying to display its address/coordinate will throw an -exception because that link has been set to null. - -__Note:__ There are some internal methods that will fetch other cells from the -collection, and this too will detach the link to the collection from any cell -that you might have assigned to a variable. - ## Excel DataTypes MS Excel supports 7 basic datatypes: @@ -112,11 +55,6 @@ values beginning with `=` will be converted to a formula. Strings that aren't numeric, or that don't begin with a leading `=` will be treated as genuine string values. -Note that a numeric string that begins with a leading zero (that isn't -immediately followed by a decimal separator) will not be converted to a -numeric, so values like phone numbers (e.g. `01615991375``will remain as -strings). - This "conversion" is handled by a cell "value binder", and you can write custom "value binders" to change the behaviour of these "conversions". The standard PhpSpreadsheet package also provides an "advanced value @@ -145,37 +83,8 @@ Formats handled by the advanced value binder include: - When strings contain a newline character (`\n`), then the cell styling is set to wrap. -Basically, it attempts to mimic the behaviour of the MS Excel GUI. - -You can read more about value binders [later in this section of the -documentation](#using-value-binders-to-facilitate-data-entry). - -### Setting a formula in a Cell - -As stated above, if you store a string value with the first character an `=` -in a cell. PHPSpreadsheet will treat that value as a formula, and then you -can evaluate that formula by calling `getCalculatedValue()` against the cell. - -There may be times though, when you wish to store a value beginning with `=` -as a string, and that you don't want PHPSpreadsheet to evaluate as though it -was a formula. - -To do this, you need to "escape" the value by setting it as "quoted text". - -```php -// Set cell A4 with a formula -$spreadsheet->getActiveSheet()->setCellValue( - 'A4', - '=IF(A3, CONCATENATE(A1, " ", A2), CONCATENATE(A2, " ", A1))' -); -$spreadsheet->getActiveSheet()->getCell('A4') - ->getStyle()->setQuotePrefix(true); -``` - -Then, even if you ask PHPSpreadsheet to return the calculated value for cell -`A4`, it will return `=IF(A3, CONCATENATE(A1, " ", A2), CONCATENATE(A2, " ", A1))` -as a string, and not try to evaluate the formula. - +You can read more about value binders later in this section of the +documentation. ### Setting a date and/or time value in a cell @@ -184,7 +93,7 @@ point value), and a number format mask is used to show how that value should be formatted; so if we want to store a date in a cell, we need to calculate the correct Excel timestamp, and set a number format mask. -```php +``` php // Get the current date/time and convert to an Excel date/time $dateTimeNow = time(); $excelDateValue = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $dateTimeNow ); @@ -219,7 +128,7 @@ behaviour. Firstly, you can set the datatype explicitly as a string so that it is not converted to a number. -```php +``` php // Set cell A8 with a numeric value, but tell PhpSpreadsheet it should be treated as a string $spreadsheet->getActiveSheet()->setCellValueExplicit( 'A8', @@ -231,7 +140,7 @@ $spreadsheet->getActiveSheet()->setCellValueExplicit( Alternatively, you can use a number format mask to display the value with leading zeroes. -```php +``` php // Set cell A9 with a numeric value $spreadsheet->getActiveSheet()->setCellValue('A9', 1513789642); // Set a number format mask to display the value as 11 digits with leading zeroes @@ -245,7 +154,7 @@ $spreadsheet->getActiveSheet()->getStyle('A9') With number format masking, you can even break up the digits into groups to make the value more easily readable. -```php +``` php // Set cell A10 with a numeric value $spreadsheet->getActiveSheet()->setCellValue('A10', 1513789642); // Set a number format mask to display the value as 11 digits with leading zeroes @@ -268,7 +177,7 @@ writers (Xlsx and Xls). It is also possible to set a range of cell values in a single call by passing an array of values to the `fromArray()` method. -```php +``` php $arrayData = [ [NULL, 2010, 2011, 2012], ['Q1', 12, 15, 21], @@ -291,7 +200,7 @@ If you pass a 2-d array, then this will be treated as a series of rows and columns. A 1-d array will be treated as a single row, which is particularly useful if you're fetching an array of data from a database. -```php +``` php $rowArray = ['Value1', 'Value2', 'Value3', 'Value4']; $spreadsheet->getActiveSheet() ->fromArray( @@ -308,7 +217,7 @@ If you have a simple 1-d array, and want to write it as a column, then the following will convert it into an appropriately structured 2-d array that can be fed to the `fromArray()` method: -```php +``` php $rowArray = ['Value1', 'Value2', 'Value3', 'Value4']; $columnArray = array_chunk($rowArray, 1); $spreadsheet->getActiveSheet() @@ -322,13 +231,13 @@ $spreadsheet->getActiveSheet() ![07-simple-example-4.png](./images/07-simple-example-4.png) -## Retrieving a cell value +## Retrieving a cell value by coordinate To retrieve the value of a cell, the cell should first be retrieved from the worksheet using the `getCell()` method. A cell's value can be read using the `getValue()` method. -```php +``` php // Get the value from cell A1 $cellValue = $spreadsheet->getActiveSheet()->getCell('A1')->getValue(); ``` @@ -340,7 +249,7 @@ value rather than the formula itself, then use the cell's `getCalculatedValue()` method. This is further explained in [the calculation engine](./calculation-engine.md). -```php +``` php // Get the value from cell A4 $cellValue = $spreadsheet->getActiveSheet()->getCell('A4')->getCalculatedValue(); ``` @@ -349,18 +258,49 @@ Alternatively, if you want to see the value with any cell formatting applied (e.g. for a human-readable date or time value), then you can use the cell's `getFormattedValue()` method. -```php +``` php // Get the value from cell A6 $cellValue = $spreadsheet->getActiveSheet()->getCell('A6')->getFormattedValue(); ``` +## Setting a cell value by column and row + +Setting a cell value by coordinate can be done using the worksheet's +`setCellValueByColumnAndRow()` method. + +``` php +// Set cell A5 with a string value +$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow(1, 5, 'PhpSpreadsheet'); +``` + +**Note:** that column references start with `1` for column `A`. + +## Retrieving a cell value by column and row + +To retrieve the value of a cell, the cell should first be retrieved from +the worksheet using the `getCellByColumnAndRow()` method. A cell’s value can +be read again using the following line of code: + +``` php +// Get the value from cell B5 +$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(2, 5)->getValue(); +``` + +If you need the calculated value of a cell, use the following code. This +is further explained in [the calculation engine](./calculation-engine.md). + +``` php +// Get the value from cell A4 +$cellValue = $spreadsheet->getActiveSheet()->getCellByColumnAndRow(1, 4)->getCalculatedValue(); +``` + ## Retrieving a range of cell values to an array It is also possible to retrieve a range of cell values to an array in a single call using the `toArray()`, `rangeToArray()` or `namedRangeToArray()` methods. -```php +``` php $dataArray = $spreadsheet->getActiveSheet() ->rangeToArray( 'C3:E5', // The worksheet range that we want to retrieve @@ -387,7 +327,7 @@ cells within a row. Below is an example where we read all the values in a worksheet and display them in a table. -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx'); $reader->setReadDataOnly(TRUE); $spreadsheet = $reader->load("test.xlsx"); @@ -400,10 +340,8 @@ foreach ($worksheet->getRowIterator() as $row) { $cellIterator = $row->getCellIterator(); $cellIterator->setIterateOnlyExistingCells(FALSE); // This loops through all cells, // even if a cell value is not set. - // For 'TRUE', we loop through cells - // only when their value is set. - // If this method is not called, - // the default value is 'false'. + // By default, only cells that have a value + // set will be iterated. foreach ($cellIterator as $cell) { echo '' . $cell->getValue() . @@ -414,25 +352,16 @@ foreach ($worksheet->getRowIterator() as $row) { echo '' . PHP_EOL; ``` -Note that we have set the cell iterator's `setIterateOnlyExistingCells()` -to FALSE. This makes the iterator loop all cells within the worksheet -range, even if they have not been set. - -The cell iterator will create a new empty cell in the worksheet if it -doesn't exist; return a `null` as the cell value if it is not set in -the worksheet; although we can also tell it to return a null value -rather than returning a new empty cell. -Setting the cell iterator's `setIterateOnlyExistingCells()` to `false` -will loop all cells in the worksheet that can be available at that -moment. If this is then set to create new cells if required, then it -will likely increase memory usage! -Only use it if it is intended to loop all cells that are possibly -available; otherwise use the option to return a null value if a cell -doesn't exist, or iterate only the cells that already exist. - -It is also possible to call the Row object's `isEmpty()` method to -determine whether you need to instantiate the Cell Iterator for that -Row. +Note that we have set the cell iterator's +`setIterateOnlyExistingCells()` to FALSE. This makes the iterator loop +all cells within the worksheet range, even if they have not been set. + +The cell iterator will return a `null` as the cell value if it is not +set in the worksheet. Setting the cell iterator's +`setIterateOnlyExistingCells()` to `false` will loop all cells in the +worksheet that can be available at that moment. This will create new +cells if required and increase memory usage! Only use it if it is +intended to loop all cells that are possibly available. ### Looping through cells using indexes @@ -445,22 +374,22 @@ loops. Below is an example where we read all the values in a worksheet and display them in a table. -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx'); $reader->setReadDataOnly(TRUE); $spreadsheet = $reader->load("test.xlsx"); $worksheet = $spreadsheet->getActiveSheet(); // Get the highest row and column numbers referenced in the worksheet -$highestRow = $worksheet->getHighestDataRow(); // e.g. 10 -$highestColumn = $worksheet->getHighestDataColumn(); // e.g 'F' +$highestRow = $worksheet->getHighestRow(); // e.g. 10 +$highestColumn = $worksheet->getHighestColumn(); // e.g 'F' $highestColumnIndex = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn); // e.g. 5 echo '' . "\n"; for ($row = 1; $row <= $highestRow; ++$row) { echo '' . PHP_EOL; for ($col = 1; $col <= $highestColumnIndex; ++$col) { - $value = $worksheet->getCell([$col, $row])->getValue(); + $value = $worksheet->getCellByColumnAndRow($col, $row)->getValue(); echo '' . PHP_EOL; } echo '' . PHP_EOL; @@ -471,17 +400,17 @@ echo '
' . $value . '
' . PHP_EOL; Alternatively, you can take advantage of PHP's "Perl-style" character incrementors to loop through the cells by coordinate: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx'); $reader->setReadDataOnly(TRUE); $spreadsheet = $reader->load("test.xlsx"); $worksheet = $spreadsheet->getActiveSheet(); // Get the highest row number and column letter referenced in the worksheet -$highestRow = $worksheet->getHighestDataRow(); // e.g. 10 -$highestColumn = $worksheet->getHighestDataColumn(); // e.g 'F' +$highestRow = $worksheet->getHighestRow(); // e.g. 10 +$highestColumn = $worksheet->getHighestColumn(); // e.g 'F' // Increment the highest column letter -++$highestColumn; +$highestColumn++; echo '' . "\n"; for ($row = 1; $row <= $highestRow; ++$row) { @@ -512,20 +441,20 @@ types of entered data using a cell's `setValue()` method (the Optionally, the default behaviour of PhpSpreadsheet can be modified, allowing easier data entry. For example, a `\PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder` class is available. -It automatically converts percentages, numbers in scientific format, and +It automatically converts percentages, number in scientific format, and dates entered as strings to the correct format, also setting the cell's style information. The following example demonstrates how to set the value binder in PhpSpreadsheet: -```php -// Older method using static property +``` php +/** PhpSpreadsheet */ +require_once 'src/Boostrap.php'; + +// Set value binder \PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); -// Create new Spreadsheet object -$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); -// Preferred method using dynamic property since 3.4.0 +// Create new Spreadsheet object $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); -$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); // ... // Add some data, resembling some different data types @@ -538,54 +467,8 @@ $spreadsheet->getActiveSheet()->setCellValue('A5', 'Date/time value:'); $spreadsheet->getActiveSheet()->setCellValue('B5', '21 December 1983'); ``` -Alternatively, a `\PhpOffice\PhpSpreadsheet\Cell\StringValueBinder` class is available -if you want to preserve all content as strings. This might be appropriate if you -were loading a file containing values that could be interpreted as numbers (e.g. numbers -with leading sign such as international phone numbers like `+441615579382`), but that -should be retained as strings (non-international phone numbers with leading zeroes are -already maintained as strings). - -By default, the StringValueBinder will cast any datatype passed to it into a string. However, there are a number of settings which allow you to specify that certain datatypes shouldn't be cast to strings, but left "as is": - -```php -// Set value binder -$stringValueBinder = new \PhpOffice\PhpSpreadsheet\Cell\StringValueBinder(); -$stringValueBinder->setNumericConversion(false) - ->setSetIgnoredErrors(true) // suppresses "number stored as text" indicators - ->setBooleanConversion(false) - ->setNullConversion(false) - ->setFormulaConversion(false); -// Older method using static property -\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( $stringValueBinder ); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); -$spreadsheet->setValueBinder( $stringValueBinder ); -``` - -You can override the current binder when setting individual cell values by specifying a different Binder to use in the Cell's `setValue()` or the Worksheet's `setCellValue()` methods. -```php -$spreadsheet = new Spreadsheet(); -// Old method using static property -Cell::setValueBinder(new AdvancedValueBinder()); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet->setValueBinder(new AdvancedValueBinder()); - -$value = '12.5%'; - -$cell = $spreadsheet->getActiveSheet()->getCell('A1'); -// Value will be set as a number 0.125 with a format mask '0.00%' -$cell->setValue($value); // Using the Advanced Value Binder - -$cell = $spreadsheet->getActiveSheet()->getCell('A2'); -// Value will be set as a string '12.5%' with a format mask 'General' -$cell->setValue($value, new StringValueBinder()); // Overriding the Advanced Value Binder -``` - - -### Creating your own value binder - -Creating your own value binder is relatively straightforward. When more specialised -value binding is required, you can implement the -`\PhpOffice\PhpSpreadsheet\Cell\IValueBinder` interface or extend the existing +**Creating your own value binder is easy.** When advanced value binding +is required, you can implement the +`\PhpOffice\PhpSpreadsheet\Cell\IValueBinder` interface or extend the `\PhpOffice\PhpSpreadsheet\Cell\DefaultValueBinder` or `\PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder` classes. diff --git a/docs/topics/architecture.md b/docs/topics/architecture.md index 1c544ef746..0295d672d8 100644 --- a/docs/topics/architecture.md +++ b/docs/topics/architecture.md @@ -43,7 +43,7 @@ PhpSpreadsheet supports fluent interfaces in most locations. This means that you can easily "chain" calls to specific methods without requiring a new PHP statement. For example, take the following code: -```php +``` php $spreadsheet->getProperties()->setCreator("Maarten Balliauw"); $spreadsheet->getProperties()->setLastModifiedBy("Maarten Balliauw"); $spreadsheet->getProperties()->setTitle("Office 2007 XLSX Test Document"); @@ -55,7 +55,7 @@ $spreadsheet->getProperties()->setCategory("Test result file"); This can be rewritten as: -```php +``` php $spreadsheet->getProperties() ->setCreator("Maarten Balliauw") ->setLastModifiedBy("Maarten Balliauw") diff --git a/docs/topics/autofilters.md b/docs/topics/autofilters.md index a802836971..66321ee9dc 100644 --- a/docs/topics/autofilters.md +++ b/docs/topics/autofilters.md @@ -42,7 +42,7 @@ column, such as "Equals a red cell color" or "Larger than 150". To set an autoFilter on a range of cells. -```php +``` php $spreadsheet->getActiveSheet()->setAutoFilter('A1:E20'); ``` @@ -56,7 +56,7 @@ developer to avoid such errors. If you want to set the whole worksheet as an autofilter region -```php +``` php $spreadsheet->getActiveSheet()->setAutoFilter( $spreadsheet->getActiveSheet() ->calculateWorksheetDimension() @@ -65,13 +65,6 @@ $spreadsheet->getActiveSheet()->setAutoFilter( This enables filtering, but does not actually apply any filters. -After setting the range, you can change it so that the end row is the -last row used on the worksheet: - -```php -$spreadsheet->getActiveSheet()->getAutoFilter()->setRangeToMaxRow(); -``` - ## Autofilter Expressions PHPEXcel 1.7.8 introduced the ability to actually create, read and write @@ -81,7 +74,7 @@ will extend this to other formats. To apply a filter expression to an autoFilter range, you first need to identify which column you're going to be applying this filter to. -```php +``` php $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); $columnFilter = $autoFilter->getColumn('C'); ``` @@ -106,8 +99,6 @@ results are unpredictable. Other filter expression types (such as cell colour filters) are not yet supported. -String comparisons in filters are case-insensitive. - ### Simple filters In MS Excel, Simple Filters are a dropdown list of all values used in @@ -122,10 +113,8 @@ will be hidden. To create a filter expression, we need to start by identifying the filter type. In this case, we're just going to specify that this filter is a standard filter. -*Please note that Excel regards only tests for equal as a standard filter; -all others, including tests for not equal, must be supplied as custom filters.* -```php +``` php $columnFilter->setFilterType( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER ); @@ -138,7 +127,7 @@ When creating a simple filter in PhpSpreadsheet, you only need to specify the values for "checked" columns: you do this by creating a filter rule for each value. -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, @@ -163,7 +152,7 @@ standard filters are always treated as being joined by an OR condition. If you want to create a filter to select blank cells, you would use: -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, @@ -181,7 +170,7 @@ within a year, or individual days within each month. DateGroup filters are still applied as a Standard Filter type. -```php +``` php $columnFilter->setFilterType( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_FILTER ); @@ -192,7 +181,7 @@ for "checked" columns as an associative array of year. month, day, hour minute and second. To select a year and month, you need to create a DateGroup rule identifying the selected year and month: -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, @@ -240,7 +229,7 @@ either an AND or an OR. We start by specifying a Filter type, this time a CUSTOMFILTER. -```php +``` php $columnFilter->setFilterType( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER ); @@ -251,7 +240,7 @@ And then define our rules. The following shows a simple wildcard filter to show all column entries beginning with the letter `U`. -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, @@ -262,21 +251,20 @@ $columnFilter->createRule() ); ``` -MS Excel uses `*` as a wildcard to match any number of characters, and `?` -as a wildcard to match a single character. `U*` equates to "begins with -a 'U'"; `*U` equates to "ends with a 'U'"; and `*U*` equates to -"contains a 'U'". -Note that PhpSpreadsheet recognizes wildcards only for equal/not-equal tests. +MS Excel uses \* as a wildcard to match any number of characters, and ? +as a wildcard to match a single character. 'U\*' equates to "begins with +a 'U'"; '\*U' equates to "ends with a 'U'"; and '\*U\*' equates to +"contains a 'U'" -If you want to match explicitly against `*` or `?`, you can -escape it with a tilde `~`, so `?~**` would explicitly match for `*` -as the second character in the cell value, followed by any +If you want to match explicitly against a \* or a ? character, you can +escape it with a tilde (\~), so ?\~\*\* would explicitly match for a \* +character as the second character in the cell value, followed by any number of other characters. The only other character that needs escaping -is the `~` itself. +is the \~ itself. To create a "between" condition, we need to define two rules: -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, @@ -301,9 +289,9 @@ This defined two rules, filtering numbers that are `>= -20` OR `<= 20`, so we also need to modify the join condition to reflect AND rather than OR. -```php -$columnFilter->setJoin( - \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND +``` php +$columnFilter->setAndOr( + \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_ANDOR_AND ); ``` @@ -332,21 +320,21 @@ column at a time. Again, we start by specifying a Filter type, this time a DYNAMICFILTER. -```php +``` php $columnFilter->setFilterType( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER ); ``` When defining the rule for a dynamic filter, we don't define a value (we -can simply set that to null string) but we do specify the dynamic filter +can simply set that to NULL) but we do specify the dynamic filter category. -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL, - '', + NULL, \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE ) ->setRuleType( @@ -432,7 +420,7 @@ column at a time. We start by specifying a Filter type, this time a DYNAMICFILTER. -```php +``` php $columnFilter->setFilterType( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER ); @@ -440,7 +428,7 @@ $columnFilter->setFilterType( Then we create the rule: -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT, @@ -456,7 +444,7 @@ This will filter the Top 5 percent of values in the column. To specify the lowest (bottom 2 values), we would specify a rule of: -```php +``` php $columnFilter->createRule() ->setRule( \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE, @@ -502,7 +490,7 @@ If you wish to execute your filter from within a script, you need to do this manually. You can do this using the autofilters `showHideRows()` method. -```php +``` php $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); $autoFilter->showHideRows(); ``` @@ -510,31 +498,14 @@ $autoFilter->showHideRows(); This will set all rows that match the filter criteria to visible, while hiding all other rows within the autofilter area. -Excel allows you to explicitly hide a row after applying a filter even -if the row wasn't hidden by the filter. However, if a row is hidden *before* -applying the filter, and the filter is applied, the row will no longer be hidden. -This can make a difference during PhpSpreadsheet save, since PhpSpreadsheet -will apply the filter during save if it hasn't been previously applied, -or if the filter criteria have changed since it was last applied. -Note that an autofilter read in from an existing spreadsheet is assumed to have been applied. -Also note that changing the data in the columns being filtered -does not result in reevaluation in either Excel or PhpSpreadsheet. -If you wish to re-apply all filters in the spreadsheet -(possibly just before save): -```php -$spreadsheet->reevaluateAutoFilters(false); -``` -You can specify `true` rather than `false` to adjust the filter ranges -on each sheet so that they end at the last row used on the sheet. - ### Displaying Filtered Rows Simply looping through the rows in an autofilter area will still access -every row, whether it matches the filter criteria or not. To selectively +ever row, whether it matches the filter criteria or not. To selectively access only the filtered rows, you need to test each row’s visibility settings. -```php +``` php foreach ($spreadsheet->getActiveSheet()->getRowIterator() as $row) { if ($spreadsheet->getActiveSheet() ->getRowDimension($row->getRowIndex())->getVisible()) { diff --git a/docs/topics/calculation-engine.md b/docs/topics/calculation-engine.md index ca628c0a7c..f1d1c2c127 100644 --- a/docs/topics/calculation-engine.md +++ b/docs/topics/calculation-engine.md @@ -10,12 +10,10 @@ formula calculation capabilities. A cell can be of a value type which can be evaluated). For example, the formula `=SUM(A1:A10)` evaluates to the sum of values in A1, A2, ..., A10. -Calling `getValue()` on a cell that contains a formula will return the formula itself. - To calculate a formula, you can call the cell containing the formula’s method `getCalculatedValue()`, for example: -```php +``` php $spreadsheet->getActiveSheet()->getCell('E11')->getCalculatedValue(); ``` @@ -24,24 +22,6 @@ with PhpSpreadsheet, it evaluates to the value "64": ![09-command-line-calculation.png](./images/09-command-line-calculation.png) -Calling `getCalculatedValue()` on a cell that doesn't contain a formula will simply return the value of that cell; but if the cell does contain a formula, then PhpSpreadsheet will evaluate that formula to calculate the result. - -There are a few useful mehods to help identify whether a cell contains a formula or a simple value; and if a formula, to provide further information about it: - -```php -$spreadsheet->getActiveSheet()->getCell('E11')->isFormula(); -``` -will return a boolean true/false, telling you whether that cell contains a formula or not, so you can determine if a call to `getCalculatedVaue()` will need to perform an evaluation. - -For more details on working with array formulas, see the [the recipes documentationn](./recipes.md/#array-formulas). - -When writing a formula to a cell, formulas should always be set as they would appear in an English version of Microsoft Office Excel, and PhpSpreadsheet handles all formulas internally in this format. This means that the following rules hold: - - - Decimal separator is `.` (period) - - Function argument separator is `,` (comma) - - Matrix row separator is `;` (semicolon) - - English function names must be used - Another nice feature of PhpSpreadsheet's formula parser, is that it can automatically adjust a formula when inserting/removing rows/columns. Here's an example: @@ -52,7 +32,7 @@ You see that the formula contained in cell E11 is "SUM(E4:E9)". Now, when I write the following line of code, two new product lines are added: -```php +``` php $spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2); ``` @@ -63,35 +43,6 @@ inserted 2 new rows), changed to "SUM(E4:E11)". Also, the inserted cells duplicate style information of the previous cell, just like Excel's behaviour. Note that you can both insert rows and columns. -If you want to "anchor" a specific cell for a formula, then you prefix the column and/or the row with a `$` symbol, exactly as you would in MS Excel itself. -So if a formula contains "SUM(E$4:E9)", and you insert 2 new rows after row 1, the formula will be adjusted to read "SUM(E$4:E11)", with the `$` fixing row 4 as the start of the range. - - - -## Calculation Cache - -Once the Calculation engine has evaluated the formula in a cell, the result -will be cached, so if you call `getCalculatedValue()` a second time for the -same cell, the result will be returned from the cache rather than evaluating -the formula a second time. This helps boost performance, because evaluating -a formula is an expensive operation in terms of performance and speed. - -However, there may be times when you don't want this, perhaps you've changed -the underlying data and need to re-evaluate the same formula with that new -data. - -```php -Calculation::getInstance($spreadsheet)->disableCalculationCache(); -``` - -Will disable calculation caching, and flush the current calculation cache. - -If you want only to flush the cache, then you can call - -```php -Calculation::getInstance($spreadsheet)->clearCalculationCache(); -``` - ## Known limitations There are some known limitations to the PhpSpreadsheet calculation @@ -104,11 +55,6 @@ formula calculation is subject to PHP's language characteristics. Not all functions are supported, for a comprehensive list, read the [function list by name](../references/function-list-by-name.md). -#### Array arguments for Function Calls in Formulas - -While most of the Excel function implementations now support array arguments, there are a few that should accept arrays as arguments but don't do so. -In these cases, the result may be a single value rather than an array; or it may be a `#VALUE!` error. - #### Operator precedence In Excel `+` wins over `&`, just like `*` wins over `+` in ordinary @@ -116,7 +62,7 @@ algebra. The former rule is not what one finds using the calculation engine shipped with PhpSpreadsheet. - [Reference for Excel](https://support.office.com/en-us/article/Calculation-operators-and-precedence-in-Excel-48be406d-4975-4d31-b2b8-7af9e0e2878a) -- [Reference for PHP](https://php.net/manual/en/language.operators.php) +- [Reference for PHP](http://php.net/manual/en/language.operators.php) #### Formulas involving numbers and text @@ -128,7 +74,7 @@ formula is evaluated as 3 instead of evaluating as an error. This also causes the Excel document being generated as containing unreadable content. -- [Reference for this behaviour in PHP](https://php.net/manual/en/language.types.string.php#language.types.string.conversion) +- [Reference for this behaviour in PHP](http://php.net/manual/en/language.types.string.php#language.types.string.conversion) #### Formulas don’t seem to be calculated in Excel2003 using compatibility pack? @@ -136,10 +82,6 @@ This is normal behaviour of the compatibility pack, Xlsx displays this correctly. Use `\PhpOffice\PhpSpreadsheet\Writer\Xls` if you really need calculated values, or force recalculation in Excel2003. -#### PAD (Precision As Displayed) Not Supported - -There are no plans to support Precision As Displayed. - ## Handling Date and Time Values ### Excel functions that return a Date and Time value @@ -152,7 +94,7 @@ date values by calling the `\PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType()` method: -```php +``` php \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType($returnDateType); ``` @@ -168,7 +110,7 @@ if an invalid value is passed in for the return date type). The `\PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType()` method can be used to determine the current value of this setting: -```php +``` php $returnDateType = \PhpOffice\PhpSpreadsheet\Calculation\Functions::getReturnDateType(); ``` @@ -183,7 +125,7 @@ number of seconds from the PHP/Unix base date. The PHP/Unix base date (0) is 00:00 UST on 1st January 1970. This value can be positive or negative: so a value of -3600 would be 23:00 hrs on 31st December 1969; while a value of +3600 would be 01:00 hrs on 1st January 1970. This -gives 32-bit PHP a date range of between 14th December 1901 and 19th January +gives PHP a date range of between 14th December 1901 and 19th January 2038. #### PHP `DateTime` Objects @@ -206,7 +148,7 @@ It is possible for scripts to change the calendar used for calculating Excel date values by calling the `\PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar()` method: -```php +``` php \PhpOffice\PhpSpreadsheet\Shared\Date::setExcelCalendar($baseDate); ``` @@ -221,7 +163,7 @@ if an invalid value is passed in). The `\PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar()` method can be used to determine the current value of this setting: -```php +``` php $baseDate = \PhpOffice\PhpSpreadsheet\Shared\Date::getExcelCalendar(); ``` @@ -343,19 +285,6 @@ and false is failure (e.g. an invalid DateTimeZone value was passed.) These functions support a timezone as an optional second parameter. This applies a specific timezone to that function call without affecting the default PhpSpreadsheet Timezone. -### Calculating Value of Date/Time Read From Spreadsheet - -Nothing special needs to be done to interpret Date/Time values entered directly into a spreadsheet. They will have been stored as numbers with an appropriate number format set for the cell. However, depending on their value, they may have been stored as either integer or float values. If that is a problem, you can force `getCalculatedValue` to return float rather than int depending on the number format used for the cell. - -```php -// All fields with Date, Time, or DateTime styles returned as float. -\PhpOffice\PhpSpreadsheet\Cell\Cell::setCalculateDateTimeType(\PhpOffice\PhpSpreadsheet\Cell\Cell::CALCULATE_DATE_TIME_FLOAT); -// All fields with Time or DateTime styles returned as float. -\PhpOffice\PhpSpreadsheet\Cell\Cell::setCalculateDateTimeType(\PhpOffice\PhpSpreadsheet\Cell\Cell::CALCULATE_TIME_FLOAT); -// Default - fields with Date, Time, or DateTime styles returned as they had been stored. -\PhpOffice\PhpSpreadsheet\Cell\Cell::setCalculateDateTimeType(\PhpOffice\PhpSpreadsheet\Cell\Cell::CALCULATE_DATE_TIME_ASIS); -``` - ## Function Reference ### Database Functions @@ -400,7 +329,7 @@ This is the statistical mean. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -468,7 +397,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -503,7 +432,7 @@ has not yet been implemented in PhpSpreadsheet. #### DCOUNTA -The DCOUNTA function returns the count of cells that aren’t blank in a +The DCOUNT function returns the count of cells that aren’t blank in a column of a list or database and that match conditions that you specify. ##### Syntax @@ -539,7 +468,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -610,7 +539,7 @@ in which you specify a condition for the column. #### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -678,7 +607,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -746,7 +675,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -814,7 +743,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -883,7 +812,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -952,7 +881,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -1020,7 +949,7 @@ in which you specify a condition for the column. ##### Examples -```php +``` php $database = [ [ 'Tree', 'Height', 'Age', 'Yield', 'Profit' ], [ 'Apple', 18, 20, 14, 105.00 ], @@ -1121,7 +1050,7 @@ or an Excel timestamp value (real), depending on the value of ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Year') ->setCellValue('A2', 'Month') ->setCellValue('A3', 'Day'); @@ -1136,7 +1065,7 @@ $retVal = $worksheet->getCell('D1')->getCalculatedValue(); // $retVal = 1230681600 ``` -```php +``` php // We're going to be calling the same cell calculation multiple times, // and expecting different return values, so disable calculation cacheing \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE); @@ -1217,7 +1146,7 @@ the third parameter. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Year') ->setCellValue('A2', 'Month') ->setCellValue('A3', 'Day'); @@ -1255,7 +1184,7 @@ $retVal = $worksheet->getCell('D6')->getCalculatedValue(); // $retVal = 30 ``` -```php +``` php $date1 = 1193317015; // PHP timestamp for 25-Oct-2007 $date2 = 1449579415; // PHP timestamp for 8-Dec-2015 @@ -1326,7 +1255,7 @@ or an Excel timestamp value (real), depending on the value of ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String'); ->setCellValue('A2', '31-Dec-2008') ->setCellValue('A3', '31/12/2008') @@ -1348,7 +1277,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue(); // $retVal = 39813.0 for all cases ``` -```php +``` php // We're going to be calling the same cell calculation multiple times, // and expecting different return values, so disable calculation cacheing \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->setCalculationCacheEnabled(FALSE); @@ -1418,7 +1347,7 @@ This is an integer ranging from 1 to 31. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String') ->setCellValue('A2', '31-Dec-2008') ->setCellValue('A3', '14-Feb-2008'); @@ -1433,7 +1362,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue(); // $retVal = 14 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'DAYOFMONTH'], ['25-Dec-2008'] @@ -1491,7 +1420,7 @@ day year. ##### Examples -```php +``` php $worksheet->setCellValue('B1', 'Start Date') ->setCellValue('C1', 'End Date') ->setCellValue('A2', 'Year') @@ -1516,7 +1445,7 @@ $retVal = $worksheet->getCell('E4')->getCalculatedValue(); // $retVal = 1557 ``` -```php +``` php $date1 = 37655.0; // Excel timestamp for 25-Oct-2007 $date2 = 39233.0; // Excel timestamp for 8-Dec-2015 @@ -1576,7 +1505,7 @@ or an Excel timestamp value (real), depending on the value of ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String') ->setCellValue('A2', '1-Jan-2008') ->setCellValue('A3', '29-Feb-2008'); @@ -1595,7 +1524,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue(); // $retVal = 39141.0 (28-Feb-2007) ``` -```php +``` php \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType( \PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL ); @@ -1649,7 +1578,7 @@ or an Excel timestamp value (real), depending on the value of ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String') ->setCellValue('A2', '1-Jan-2000') ->setCellValue('A3', '14-Feb-2009'); @@ -1666,7 +1595,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue(); // $retVal = 39507.0 (29-Feb-2008) ``` -```php +``` php \PhpOffice\PhpSpreadsheet\Calculation\Functions::setReturnDateType( \PhpOffice\PhpSpreadsheet\Calculation\Functions::RETURNDATE_EXCEL ); @@ -1708,7 +1637,7 @@ This is an integer ranging from 0 to 23. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Time String') ->setCellValue('A2', '31-Dec-2008 17:30') ->setCellValue('A3', '14-Feb-2008 4:20 AM') @@ -1728,7 +1657,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue(); // $retVal = 16 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'HOUROFDAY'], ['09:30'] @@ -1766,7 +1695,7 @@ This is an integer ranging from 0 to 59. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Time String') ->setCellValue('A2', '31-Dec-2008 17:30') ->setCellValue('A3', '14-Feb-2008 4:20 AM') @@ -1786,7 +1715,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue(); // $retVal = 45 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MINUTE'], ['09:30'] @@ -1824,7 +1753,7 @@ This is an integer ranging from 1 to 12. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String'); $worksheet->setCellValue('A2', '31-Dec-2008'); $worksheet->setCellValue('A3', '14-Feb-2008'); @@ -1839,7 +1768,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue(); // $retVal = 2 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'MONTHOFYEAR'], ['14-July-2008'] @@ -1894,10 +1823,10 @@ The number of working days between startDate and endDate. ##### Examples -```php +``` php ``` -```php +``` php ``` ##### Notes @@ -1927,10 +1856,10 @@ or an Excel timestamp value (real), depending on the value of ##### Examples -```php +``` php ``` -```php +``` php ``` ##### Notes @@ -1964,7 +1893,7 @@ This is an integer ranging from 0 to 59. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Time String') ->setCellValue('A2', '31-Dec-2008 17:30:20') ->setCellValue('A3', '14-Feb-2008 4:20 AM') @@ -1984,7 +1913,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue(); // $retVal = 59 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'SECOND'], ['09:30:17'] @@ -2049,7 +1978,7 @@ value of method. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String') ->setCellValue('A2', '31-Dec-2008') ->setCellValue('A3', '14-Feb-2008'); @@ -2068,7 +1997,7 @@ $retVal = $worksheet->getCell('B4')->getCalculatedValue(); // $retVal = 2 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'WEEKDAY'], ['14-July-2008'] @@ -2113,7 +2042,7 @@ This is an integer year value. ##### Examples -```php +``` php $worksheet->setCellValue('A1', 'Date String') ->setCellValue('A2', '17-Jul-1982') ->setCellValue('A3', '16-Apr-2009'); @@ -2128,7 +2057,7 @@ $retVal = $worksheet->getCell('B3')->getCalculatedValue(); // $retVal = 2009 ``` -```php +``` php $retVal = call_user_func_array( ['\PhpOffice\PhpSpreadsheet\Calculation\Functions', 'YEAR'], ['14-July-2001'] diff --git a/docs/topics/conditional-formatting.md b/docs/topics/conditional-formatting.md deleted file mode 100644 index 735215c628..0000000000 --- a/docs/topics/conditional-formatting.md +++ /dev/null @@ -1,791 +0,0 @@ -# Conditional Formatting - -## Introduction - -In addition to standard cell formatting options, most spreadsheet software provides an option known as Conditional Formatting, which allows formatting options to be set based on the value of a cell. - -The cell's standard formatting defines most style elements that will always be applied, such as the font face and size; but Conditional Formatting allows you to override some elements of that cell style such as number format mask; font colour, bold, italic and underlining; borders; and fill colour and pattern. - -Conditional Formatting can be applied to individual cells, or to a range of cells. - -### Example - -As a simple example in MS Excel itself, if we wanted to highlight all cells in the range A1:A10 that contain values greater than 80, start by selecting the range of cells. - -![11-01-CF-Simple-Select-Range.png](./images/11-01-CF-Simple-Select-Range.png) - -On the Home tab, in the "Styles" group, click "Conditional Formatting". This allows us to select an Excel Wizard to guide us through the process of creating a Conditional Rule and defining a Style for that rule. - -![11-02-CF-Simple-Tab.png](./images/11-02-CF-Simple-Tab.png) - -Click "Highlight Cells Rules", then "Greater Than". - -![11-03-CF-Simple-CellIs-GreaterThan.png](./images/11-03-CF-Simple-CellIs-GreaterThan.png) - -Enter the value "80" in the prompt box; and either select one of the pre-defined formatting style (or create a custom style from there). - -![11-04-CF-Simple-CellIs-Value-and-Style.png](./images/11-04-CF-Simple-CellIs-Value-and-Style.png) - -Then click "OK". The rule is immediately applied to the selected range of cells, highlighting all those with a value greater than 80 in the chosen style. - -![11-05-CF-Simple-CellIs-Highlighted.png](./images/11-05-CF-Simple-CellIs-Highlighted.png) - -Any change to the value of a cell within that range will immediately check the rule, and automatically apply the new styling if it applies. - -![11-06-CF-Simple-Cell-Value-Change.png](./images/11-06-CF-Simple-Cell-Value-Change.png) - -If we wanted to set up the same Conditional Formatting rule in PHPSpreadsheet, we would do so using the following code: - -```php -$conditional = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); -$conditional->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS); -$conditional->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_GREATERTHAN); -$conditional->addCondition(80); -$conditional->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN); -$conditional->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID); -$conditional->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN); - -$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles(); -$conditionalStyles[] = $conditional; - -$spreadsheet->getActiveSheet()->getStyle('A1:A10')->setConditionalStyles($conditionalStyles); -``` - -Depending on the Rules that we might want to apply for a Condition, sometimes an "operator Type" is required, sometimes not (and not all Operator Types are appropriate for all Condition Types); sometimes a "Condition" is required (or even several conditions), sometimes not, and sometimes it must be a specific Excel formula expression. -Creating conditions manually requires a good knowledge of when these different properties need to be set, and with what type of values. -This isn't something that an end-user developer should be expected to know. - -So - to eliminate this need for complex and arcane knowledge - since PHPSpreadsheet verson 1.22.0 there is also a series of Wizards that can assist with creating Conditional Formatting rules, and which are capable of setting the appropriate operators and conditions (including the sometimes complex Excel formula expressions) for a Conditional Rule: - -```php -$wizardFactory = new \PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard('A1:A10'); -$wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard::CELL_VALUE); -$wizard->greaterThan(80); -$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN); -$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID); -$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN); - -$conditional = $wizard->getConditional(); -``` -The Wizards know which operator types match up with condition types, and provide more meaningful method names for operators, and they build expressions and formulae when required; and also work well with an IDE such as PHPStorm. - ---- - -Note that `$conditionalStyles` is an array: it is possible to apply several conditions to the same range of cells. If we also wanted to highlight values that were less than 10 in the A1:A10 range, we can add a second style rule. - -In Excel, we would do this by selecting the range again, and going through the same process, this time selecting the "Highlight Cells Rules", then "Less Than" from the "Conditional Styles" menu, entering the value "10" in the prompt box, and selecting the appropriate style. - -In PHPSpreadsheet, we would do: - -```php -$conditional2 = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); -$conditional2->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS); -$conditional2->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN); -$conditional2->addCondition(10); -$conditional2->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKRED); -$conditional2->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID); -$conditional2->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED); - -$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('A1:A10')->getConditionalStyles(); -$conditionalStyles[] = $conditional2; - -$spreadsheet->getActiveSheet()->getStyle('A1:A10')->setConditionalStyles($conditionalStyles); -``` -or again, using the Wizard: -```php -$wizardFactory = new \PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard('A1:A10'); -$wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard::CELL_VALUE); -$wizard->lessThan(10); -$wizard->getStyle()->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN); -$wizard->getStyle()->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID); -$wizard->getStyle()->getFill()->getStartColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_GREEN); - -$conditional = $wizard->getConditional(); -``` - - -### Order of Evaluating Multiple Rules/Conditions - -`$conditionalStyles` is an array, which not only represents multiple conditions that can be applied to a cell (or range of cells), but also the order in which they are checked. Some spreadsheet programs stop processing conditions once they find a match. On the other hand, MS Excel will check each of those conditions in turn in the order they are defined. It will stop checking only if it finds a matching rule that specifies 'stop if true'; however, if it finds conflicting matches with conflicting formatting (e.g. both set a background fill color but use different choices), the first match wins. In either case, this means that the order of checking conditions can be important. - -Consider the following. We have one condition that checks if a cell value is between -2 and 2, styling the fill color of the cell in yellow if that condition matches; and a second condition that checks if the cell value is equal to 0, styling the fill color of the cell in red if that matches. - - Yellow if value is between -2 and 2 - - Red if value equals 0 - -If they are evaluated in the order I've described above, and the cell has a value of 0, then the first rule will match (because 0 is between -2 and 2), and the cell will be styled in yellow, and no further conditions will be checked. So the rule that styles the cell in red if the value is 0 will never be assessed, even though that would also match (and is probably what we actually wanted, otherwise why have an explicit rule defined for that condition). - -![11-20-CF-Rule-Order-1.png](./images/11-20-CF-Rule-Order-1.png) - -If the rule order is reversed - - Red if value equals 0 - - Yellow if value is between -2 and 2 - -then the cell containing the value 0 will be rendered in red, because that is the first matching condition; and the formatting in the other condition conflicts with this, so is discarded. - -![11-21-CF-Rule-Order-2.png](./images/11-21-CF-Rule-Order-2.png) - -So when you have multiple conditions where the rules might "overlap", the order of these is important. - -If the cell matches multiple conditions, Excel (but not most other spreadsheet programs) will apply non-conflicting styles from each match. So, for the example above, if we wanted a match of 0 to have a different *font* color rather than a different *fill* color, Excel can honor both. - -![11-21-CF-Rule-Order-2.pic2.png](./images/11-21-CF-Rule-Order-2.pic2.png) - -Here is the same spreadsheet opened in LibreOffice - cell A4 has only the first conditional style applied to it. (You would see the same if you checked 'Stop if True' in Excel.) If you want the spreadsheet to appear the same in both Excel and LibreOffice, you would need to use more complicated conditions. - -![11-21-CF-Rule-Order-2.pic2.png](./images/11-21-CF-Rule-Order-2.pic3.png) - -PhpSpreadsheet supports the setting of [Stop If True](#stop-if-true-and-no-format-set). - - -### Reader/Writer Support - -Currently, the following Conditional Types are supported for the following Readers and Writers: - -MS Excel | Conditional Type | Readers | Writers ----|---|---|--- -| Cell Value | Conditional::CONDITION_CELLIS | Xlsx | Xlsx, Xls, Html -Specific Text | Conditional::CONDITION_CONTAINSTEXT | Xlsx | Xlsx, Html - | Conditional::CONDITION_NOTCONTAINSTEXT | Xlsx | Xlsx, Html - | Conditional::CONDITION_BEGINSWITH | Xlsx | Xlsx, Html - | Conditional::CONDITION_ENDSWITH | Xlsx | Xlsx, Html -Dates Occurring | Conditional::CONDITION_TIMEPERIOD | Xlsx | Xlsx, Html -Blanks | Conditional::CONDITION_CONTAINSBLANKS | Xlsx | Xlsx, Html -No Blanks | Conditional::CONDITION_NOTCONTAINSBLANKS | Xlsx | Xlsx, Html -Errors | Conditional::CONDITION_CONTAINSERRORS | Xlsx | Xlsx, Html -No Errors | Conditional::CONDITION_NOTCONTAINSERRORS | Xlsx | Xlsx, Html -Duplicates/Unique | Conditional::CONDITION_DUPLICATES | Xlsx | Xlsx, Html - | Conditional::CONDITION_UNIQUE | Xlsx | Xlsx, Html -Use a formula | Conditional::CONDITION_EXPRESSION | Xlsx | Xlsx, Xls, Html -Data Bars | Conditional::CONDITION_DATABAR | Xlsx | Xlsx, Html -Colour Scales | Conditional::COLORSCALE | Xlsx | Html - -To enable conditional formatting for Html writer, use: - -```php - $writer = new HtmlWriter($spreadsheet); - $writer->setConditionalFormatting(true); -``` - -The following Conditional Types are currently not supported by any Readers or Writers: - -MS Excel | Conditional Type ----|--- -Above/Below Average | ? -Top/Bottom Items | ? -Top/Bottom %age | ? -Icon Sets | ? - -Unsupported types will by ignored by the Readers, and cannot be created through PHPSpreadsheet. - - -## Wizards - -While the Wizards don't simplify defining the Conditional Style itself; they do make it easier to define the conditions (the rules) where that style will be applied. -MS Excel itself has wizards to guide the creation of Conditional Formatting rules and styles. - -![11-07-CF-Wizard.png](./images/11-07-CF-Wizard.png) - -The Wizard Factory allows us to retrieve the appropriate Wizard for the CF Rule that we want to apply. -Most of those that have already been defined fall under the "Format only cells that contain" category. -MS Excel provides a whole series of different types of rule, each of which has it's own formatting and logic. -The Wizards try to replicate this logic and behaviour, similar to Excel's own "Formatting Rule" helper wizard. - -MS Excel | Wizard Factory newRule() Type Constant | Wizard Class Name ----|---|--- -Cell Value | Wizard::CELL_VALUE | CellValue -Specific Text | Wizard::TEXT_VALUE | TextValue -Dates Occurring | Wizard::DATES_OCCURRING | DateValue -Blanks | Wizard::BLANKS | Blanks -No Blanks | Wizard::NOT_BLANKS | Blanks -Errors | Wizard::ERRORS | Errors -No Errors | Wizard::NOT_ERRORS | Errors - -Additionally, Wizards also exists for "Format only unique or duplicate values", and for "Use a formula to determine which cells to format": - -MS Excel | Wizard Factory newRule() Type Constant | Wizard Class Name ----|---|--- -Duplicates/Unique | Wizard::DUPLICATES or Wizard::UNIQUE | Duplicates -Use a formula | Wizard::EXPRESSION or Wizard::FORMULA | Expression - -There is currently no Wizard for Data Bars, even though this Conditional Type is supported by the Xlsx Reader and Writer. - ---- - -We instantiate the Wizard Factory, passing in the cell range where we want to apply Conditional Formatting rules; and can then call the `newRule()` method, passing in the type of Conditional Rule that we want to create in order to return the appropriate Wizard: - -```php -$wizardFactory = new \PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard('C3:E5'); -$wizard = $wizardFactory->newRule(\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard::CELL_VALUE); -``` -You can, of course, instantiate the Wizard that you want directly, rather than using the factory; but still remember to pass in the cell range. -```php -$wizard = new \PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard\CellValue('C3:E5'); -``` - -That Wizard then provides methods allowing us to define the rule, setting the operator and the values that we want to compare for that rule. -Note that not all rules require values, or even operators, but the individual Wizards provide whatever is necessary; and this document lists all options available for every Wizard. - -Once we have used the Wizard to define the conditions and values that we want; and have defined a style using the `setStyle()` method, then we call the Wizard's `getConditional()` method to return a Conditional object that can be added to the array of Conditional Styles that we pass to `setConditionalStyles()`. - - -### CellValue Wizard - -For the `CellValue` Wizard, we always need to provide an operator and a value; and for the "between" and "notBetween" operators, we need to provide two values to specify a range. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_CELLIS | Wizard::CELL_VALUE | Conditional::OPERATOR_EQUAL | equals() -| | Conditional::OPERATOR_NOTEQUAL | notEquals() -| | Conditional::OPERATOR_GREATERTHAN | greaterThan() -| | Conditional::OPERATOR_GREATERTHANOREQUAL | greaterThanOrEqual() -| | Conditional::OPERATOR_LESSTHAN | lessThan() -| | Conditional::OPERATOR_LESSTHANOREQUAL | lessThanOrEqual() -| | Conditional::OPERATOR_BETWEEN | between() -| | Conditional::OPERATOR_NOTBETWEEN | notBetween() -| | | and() | Used to provide the second operand for `between()` and `notBetween() - -A single operator call is required for every rule (except `between()` and `notBetween`, where the Wizard also provides `and()`); and providing a value is mandatory for all operators. -The values that we need to provide for each operator can be numeric, boolean or string literals (even NULL); cell references; or formulae. - -So to set the rule using an operator, we would make a call like: -```php -$wizard->lessThan(10); -``` -or when setting a `between()` or `notBetween()` rule, we can make use of the fluent interface with the `and()` method to set the range of values: -```php -$wizard->between(-10)->and(10); -``` -Providing a second value using `and()` is mandatory for a `between()` or `notBetween()` range. - -To retrieve the Conditional, to add it to our `$conditionalStyles` array, we call the Wizard's `getConditional()` method. -```php -$conditional = $wizard->getConditional(); -$conditionalStyles = [$conditional]; -``` -or simply -```php -$conditionalStyles[] = $wizard->getConditional(); -``` - -Putting it all together, we can use a block of code like (using pre-defined Style objects): -```php -$cellRange = 'A2:E5'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals(0) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->greaterThan(0) - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->lessThan(0) - ->setStyle($redStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -You can find an example that demonstrates this in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/01_Basic_Comparisons.php#L81 "Conditional Formatting - Simple Example") for the repo. - -![11-12-CF-Simple-Example.png](./images/11-12-CF-Simple-Example.png) - - -#### Value Types - -When we need to provide a value for an operator, that value can be numeric, boolean or string literals (even NULL); cell references; or even an Excel formulae. - -##### Literals - -If the value is a literal (even a string literal), we simply need to pass the value; the Wizard will ensure that strings are correctly quoted when we get the Conditional from the Wizard. - -```php -$wizard->equals('Hello World'); -``` -If you weren't using the Wizard, but were creating the Conditional directly, you would need to remember to wrap this value in quotes yourself (`'"Hello World"'`) - -However, a cell reference or a formula are also string data, so we need to tell the Wizard if the value that we are passing in isn't just a string literal value, but should be treated as a cell reference or as a formula. - -##### Cell References - -If we want to use the value from cell `H9` in our rule; then we need to pass a value type of `VALUE_TYPE_CELL` to the operator, in addition to the cell reference itself. - -```php -$wizard->equals('$H$9', Wizard::VALUE_TYPE_CELL); -``` - -![11-08-CF-Absolute-Cell-Reference.png](./images/11-08-CF-Absolute-Cell-Reference.png) - -You can find an example that demonstrates this in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/01_Basic_Comparisons.php#L103 "Conditional Formatting - Basic Comparisons") for the repo. - -Note that we are passing the cell as an absolute cell reference, "pinned" (with the `$` symbol) for both the row and the column. - -In this next example, we need to use relative cell references, so that the comparison will match the value in column `A` against the values in columns `B` and `C` for each row in our range (`A18:A20`); ie, test if the value in `A18` is between the values in `B18` and `C18`, test if the value in `A19` is between the values in `B19` and `C19`, etc. - -![11-09-CF-Relative-Cell-Reference.png](./images/11-09-CF-Relative-Cell-Reference.png) - -```php -$wizard->between('$B1', Wizard::VALUE_TYPE_CELL) - ->and('$C1', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); -``` - -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/01_Basic_Comparisons.php#L126 "Conditional Formatting - Basic Comparisons") for the repo. - -In this case, we "pin" the column for the address; but leave the row "unpinned". -Notice also that we treat the first cell in our range as cell `A1`: the relative row number will be adjusted automatically to match our defined range; that is, the range that we specified when we instantiated the Wizard (passed in through the Wizard Factory) when we make the call to `getConditional()`. - -##### Formulae - -It is also possible to set the value/operand as an Excel formula expression, not simply a literal value or a cell reference. -Again, we do need to specify that the value is a Formula. - -```php -$cellRange = 'C26:C28'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals('CONCATENATE($A1," ",$B1)', Wizard::VALUE_TYPE_FORMULA) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` - -You can find an example that demonstrates this in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/02_Text_Comparisons.php#L209 "Conditional Formatting - Text Comparisons") for the repo. - -When the formula contains cell references, we again need to be careful with pinning to absolute columns/rows; and when unpinned, we reference based on the top-left cell of the range being cell `A1` when we define the formula. -Here we're defining the formula as `CONCATENATE($A1," ",$B1)`, so we're "pinning" the column references for columns `A` and `B`; but leaving the row unpinned (explicitly set to start from row 1), which is then adjusted to the conditional range when we get the Conditional from the Wizard, and adjusted to the individual rows within that range when MS Excel displays the results. - -![11-13-CF-Formula-with-Relative-Cell-Reference.png](./images/11-13-CF-Formula-with-Relative-Cell-Reference.png) - - -### TextValue Wizard - -While we can use the `CellValue` Wizard to do basic string comparison rules, the `TextValue` Wizard provides rules for comparing parts of a string value. - -For the `TextValue` Wizard, we always need to provide an operator and a value. As with the `CellValue` Wizard, values can be literals (but should always be string literals), cell references, or formula. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_CONTAINSTEXT | Wizard::TEXT_VALUE | Conditional::OPERATOR_CONTAINSTEXT | contains() -Conditional::CONDITION_NOTCONTAINSTEXT | Wizard::TEXT_VALUE | Conditional::OPERATOR_NOTCONTAINS | doesNotContain() -| | | doesntContain() | synonym for `doesNotContain()` -Conditional::CONDITION_BEGINSWITH | Wizard::TEXT_VALUE | Conditional::OPERATOR_BEGINSWITH | beginsWith() -| | | startsWith() | synonym for `beginsWith()` -Conditional::CONDITION_ENDSWITH | Wizard::TEXT_VALUE | Conditional::OPERATOR_ENDSWITH | endsWith() - -The Conditional actually uses a separate "Condition Type" for each option, each with its own "Operator Type", and the condition should be an Excel formula (not simply the string value to check), and with a custom `text` attribute. The Wizard should make it a lot easier to create these conditional rules. - -To create a Conditional rule manually, you would need to do something like: -```php -$cellRange = 'A14:B16'; -$conditionalStyles = []; -$conditional = new Conditional(); -// Remember to use the correct Condition Type -$conditional->setConditionType(Conditional::CONDITION_CONTAINSTEXT); -// Remember to use the correct Operator Type -$conditional->setOperatorType(Conditional::OPERATOR_CONTAINSTEXT); -// Remember to set the text attribute -// Remember to wrap the string literal -$conditional->setText('"LL"'); -// Remember that the condition should be the first element in an array -// Remember that we need a specific formula for this Conditional -// Remember to wrap the string literal -// Remember to use the top-left cell of the range that we want to apply this rule to -$conditional->setConditions(['NOT(ISERROR(SEARCH("LL",A14)))']); -$conditional->setStyle($greenStyle); - -$conditionalStyles[] - -$spreadsheet->getActiveSheet() - ->getStyle($cellRange) - ->setConditionalStyles($conditionalStyles); -``` -But using the Wizard, the same Conditional rule can be created by: -```php -$cellRange = 'A14:B16'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->contains('LL') - ->setStyle($greenStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -You can find an example that demonstrates this in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/02_Text_Comparisons.php#L149 "Conditional Formatting - Text Comparisons") for the repo. - -![11-17-CF-Text-Contains.png](./images/11-17-CF-Text-Contains.png) - -There are also examples in that file for `notContains()`, `beginsWith()` and `endsWith()` comparisons; using literal text, and with cell references. - -The actual Excel Expressions used (and that you would need to set manually if you were defining the Conditional yourself rather than using the Wizard) are listed below: - -Conditional Type | Condition Expression ----|--- -Conditional::CONDITION_CONTAINSTEXT | NOT(ISERROR(SEARCH(``,``))) -Conditional::CONDITION_NOTCONTAINSTEXT | ISERROR(SEARCH(``,``))`,LEN(``))=`` -Conditional::CONDITION_ENDSWITH | RIGHT(``,LEN(``))=`` - -The `` always references the top-left cell in the range of cells for this Conditional Formatting Rule. -The `` should be wrapped in double quotes (`"`) for string literals; but unquoted if it is a value stored in a cell reference, or a formula. -The `TextValue` Wizard handles defining these expressions for you. - -As with the operand for the `CellValue` Wizard, you can specify the value passed to `contains()`, `doesNotContain()`, `beginsWith()` and `endsWith()` as a cell reference, or as a formula; and if you do so, then you need to pass a second argument to those methods specifying `Wizard::VALUE_TYPE_CELL` or `Wizard::VALUE_TYPE_FORMULA`. -The same rules also apply to "pinning" cell references as described above for the `CellValue` Wizard. - -```php -$textWizard->beginsWith('$D$1', Wizard::VALUE_TYPE_CELL) - ->setStyle($yellowStyle); -``` - -### DateValue Wizard - -For the `DateValue` Wizard, we always need to provide an operator; but no value is required. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_TIMEPERIOD | Wizard::DATES_OCCURRING | Conditional::TIMEPERIOD_TODAY | today() -| | Conditional::TIMEPERIOD_YESTERDAY | yesterday() -| | Conditional::TIMEPERIOD_TOMORROW | tomorrow() -| | Conditional::TIMEPERIOD_LAST_7_DAYS | last7Days() -| | | lastSevenDays() | synonym for `last7Days()` -| | Conditional::TIMEPERIOD_LAST_WEEK | lastWeek() -| | Conditional::TIMEPERIOD_THIS_WEEK | thisWeek() -| | Conditional::TIMEPERIOD_NEXT_WEEK | nextWeek() -| | Conditional::TIMEPERIOD_LAST_MONTH | lastMonth() -| | Conditional::TIMEPERIOD_THIS_MONTH | thisMonth() -| | Conditional::TIMEPERIOD_NEXT_MONTH | nextMonth() - -The Conditional has no actual "Operator Type", and the condition/value should be an Excel formula, and with a custom `timePeriod` attribute. The Wizard should make it a lot easier to create these condition rules. - -![11-18-CF-Date-Occurring-Examples.png](./images/11-18-CF-Date-Occurring-Examples.png) - -The above image shows a grid that demonstrate each of the possible Date Occurring rules, and was generated using [the code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/05_Date_Comparisons.php#L118 "Conditional Formatting - Dates Occurring Comparisons") - -Typical sample code wod look something like: -```php -$wizardFactory = new Wizard("E2:E19"); -/** @var Wizard\DateValue $dateWizard */ -$dateWizard = $wizardFactory->newRule(Wizard::DATES_OCCURRING); -$conditionalStyles = []; - -$dateWizard->last7Days() - ->setStyle($yellowStyle); - -$conditionalStyles[] = $dateWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($dateWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` - -The actual Excel Expressions used (and that you would need to set manually if you were defining the Conditional yourself rather than using the Wizard) are listed below: - -timePeriod Attribute | Condition Expression ----|--- -today | FLOOR(``,1)=TODAY()-1 -yesterday | FLOOR(``,1)=TODAY() -tomorrow | FLOOR(``,1)=TODAY()+1 -last7Days | AND(TODAY()-FLOOR(``,1)<=6,FLOOR(``,1)<=TODAY()) -lastWeek | AND(TODAY()-ROUNDDOWN(``,0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(``,0)<(WEEKDAY(TODAY())+7)) -thisWeek | AND(TODAY()-ROUNDDOWN(``,0)<=WEEKDAY(TODAY())-1,ROUNDDOWN(``,0)-TODAY()<=7-WEEKDAY(TODAY())) -nextWeek | AND(ROUNDDOWN(``,0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN(``,0)-TODAY()<(15-WEEKDAY(TODAY()))) -lastMonth | AND(MONTH(``)=MONTH(EDATE(TODAY(),0-1)),YEAR(``)=YEAR(EDATE(TODAY(),0-1))) -thisMonth | AND(MONTH(``)=MONTH(TODAY()),YEAR(``)=YEAR(TODAY())) -nextMonth | AND(MONTH(``)=MONTH(EDATE(TODAY(),0+1)),YEAR(``)=YEAR(EDATE(TODAY(),0+1))) - -The `` always references the top-left cell in the range of cells for this Conditional Formatting Rule. - - -### Blanks Wizard - -This Wizard is used to define a simple boolean state rule, to determine whether a cell is blank or not blank. -Whether created using the Wizard Factory with a rule type of `Wizard::BLANKS` or `Wizard::NOT_BLANKS`, the same `Blanks` Wizard is returned. -The only difference is that in the one case the rule state is pre-set for `CONDITION_CONTAINSBLANKS`, in the other it is pre-set for `CONDITION_NOTCONTAINSBLANKS`. -However, you can switch between the two rules using the `isBlank()` and `notBlank()` methods; and it is only at the point when you call `getConditional()` that a Conditional will be returned based on the current state of the Wizard. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_CONTAINSBLANKS | Wizard::BLANKS | - | isBlank() | Default state -| | | notBlank() -| | | isEmpty() | Synonym for `isBlank()` -| | | notEmpty() | Synonym for `notBlank()` -Conditional::CONDITION_NOTCONTAINSBLANKS | Wizard::NOT_BLANKS | - | notBlank()| Default state -| | | isBlank() -| | | isEmpty() | Synonym for `isBlank()` -| | | notEmpty() | Synonym for `notBlank()` - -The following code shows the same Blanks Wizard being used to create both Blank and Non-Blank Conditionals, using a pre-defined `$redStyle` Style object for Blanks, and a pre-defined `$greenStyle` Style object for Non-Blanks. -```php -$cellRange = 'A2:B3'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Blanks $blanksWizard */ -$blanksWizard = $wizardFactory->newRule(Wizard::BLANKS); - -$blanksWizard->setStyle($redStyle); -$conditionalStyles[] = $blanksWizard->getConditional(); - -$blanksWizard->notBlank() - ->setStyle($greenStyle); -$conditionalStyles[] = $blanksWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($blanksWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/03_Blank_Comparisons.php#L58 "Conditional Formatting - Blank Comparisons") for the repo. - -![11-10-CF-Blanks-Example.png](./images/11-10-CF-Blanks-Example.png) - -No operand/value is required for the Blanks Wizard methods; but the Conditional that is returned contains a defined expression with an Excel formula: - -Blanks Type | Condition Expression ----|--- -isBlank() | LEN(TRIM(``))=0 -notBlank() | LEN(TRIM(``))>0 - -The `` always references the top-left cell in the range of cells for this Conditional Formatting Rule. - - -### Errors Wizard - -Like the `Blanks` Wizard, this Wizard is used to define a simple boolean state rule, to determine whether a cell with a formula value results in an error or not. -Whether created using the Wizard Factory with a rule type of `Wizard::ERRORS` or `Wizard::NOT_ERRORS`, the same `Errors` Wizard is returned. -The only difference is that in the one case the rule state is pre-set for `CONDITION_CONTAINSERRORS`, in the other it is pre-set for `CONDITION_NOTCONTAINSERRORS`. -However, you can switch between the two rules using the `isError()` and `notError()` methods; and it is only at the point when you call `getConditional()` that a Conditional will be returned based on the current state of the Wizard. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_CONTAINSERRORS | Wizard::ERRORS | - | isError() | Default state -| | | notError() -Conditional::CONDITION_NOTCONTAINSERRORS | Wizard::NOT_ERRORS | - | notError()| Default state -| | | isError() - -The following code shows the same Errors Wizard being used to create both Error and Non-Error Conditionals, using a pre-defined `$redStyle` Style object for Errors, and a pre-defined `$greenStyle` Style object for Non-Errors. -```php -$cellRange = 'C2:C6'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Errors $errorsWizard */ -$errorsWizard = $wizardFactory->newRule(Wizard::ERRORS); - -$errorsWizard->setStyle($redStyle); -$conditionalStyles[] = $errorsWizard->getConditional(); - -$errorsWizard->notError() - ->setStyle($greenStyle); -$conditionalStyles[] = $errorsWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($errorsWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` - -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/04_Error_Comparisons.php#L62 "Conditional Formatting - Error Comparisons") for the repo. - -![11-11-CF-Errors-Example.png](./images/11-11-CF-Errors-Example.png) - -No operand/value is required for the Errors Wizard methods; but the Conditional that is returned contains a defined expression with an Excel formula: - -Blanks Type | Condition Expression ----|--- -isError() | ISERROR(``) -notError() | NOT(ISERROR(``)) - -The `` always references the top-left cell in the range of cells for this Conditional Formatting Rule. - - -### Duplicates/Unique Wizard - -This Wizard is used to define a simple boolean state rule, to determine whether a cell value matches any other cells with the same value within the conditional cell range, or if the value is unique in that range of cells. -It only has any meaning if it is applied to a range of cells, not to an individual cell. -Whether created using the Wizard Factory with a rule type of `Wizard::DUPLICATES` or `Wizard::UNIQUE`, the same `Duplicates` Wizard is returned. -The only difference is that in the one case the rule state is pre-set for `CONDITION_DUPLICATES`, in the other it is pre-set for `CONDITION_UNIQUE`. -However, you can switch between the two rules using the `duplicates()` and `unique()` methods; and it is only at the point when you call `getConditional()` that a Conditional will be returned based on the current state of the Wizard. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_DUPLICATES | Wizard::DUPLICATES | - | duplicates() | Default state -| | | unique() -Conditional::CONDITION_UNIQUE | Wizard::UNIQUE | - | unique()| Default state -| | | duplicates() - -The following code shows the same Duplicates Wizard being used to create both Blank and Non-Blank Conditionals, using a pre-defined `$redStyle` Style object for Blanks, and a pre-defined `$greenStyle` Style object for Non-Blanks. -```php -$cellRange = 'A2:E6'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Duplicats $duplicatesWizard */ -$duplicatesWizard = $wizardFactory->newRule(Wizard::DUPLICATES); - -$duplicatesWizard->setStyle($redStyle); -$conditionalStyles[] = $duplicatesWizard->getConditional(); - -$duplicatesWizard->unique() - ->setStyle($greenStyle); -$conditionalStyles[] = $duplicatesWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($duplicatesWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/06_Duplicate_Comparisons.php#L66 "Conditional Formatting - Duplicate/Unique Comparisons") for the repo. - -![11-19-CF-Duplicates-Uniques-Examples.png](./images/11-19-CF-Duplicates-Uniques-Examples.png) - -Duplicates/Uniques Conditions are only identified by a Condition Type in Excel, with no operator and no expression. - - -### Expression Wizard - -The `Expression` Wizard expects to be provided with an Expression, an MS Excel formula that evaluates to either false or true. - -Condition Type | Wizard Factory newRule() Type Constant | Conditional Operator Type | Wizard Methods | Notes ----|---|---|---|--- -Conditional::CONDITION_EXPRESSION | Wizard::EXPRESSION or Wizard::FORMULA | - | expression() | The argument is an Excel formula that evaluates to true or false - | | | | formula() | Synonym for `expression()` - -Just as a simple example, here's a code snippet demonstrating expressions to determine if a cell contains an odd or an even number value: -```php -$cellRange = 'A2:C11'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Expression $expressionWizard */ -$expressionWizard = $wizardFactory->newRule(Wizard::EXPRESSION); - -$expressionWizard->expression('ISODD(A1)') - ->setStyle($greenStyle); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$expressionWizard->expression('ISEVEN(A1)') - ->setStyle($yellowStyle); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($expressionWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/07_Expression_Comparisons.php#L87 "Conditional Formatting - Odd/Even Expression Comparisons") for the repo. - -![11-14-CF-Expression-Example-Odd-Even.png](./images/11-14-CF-Expression-Example-Odd-Even.png) - -As a more complicated example, let's look at a Sales Grid, and use conditional formatting to highlight sales in the "USA" region: - -```php -$greenStyleMoney = clone $greenStyle; -$greenStyleMoney->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD); - -$cellRange = 'A17:D22'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Expression $expressionWizard */ -$expressionWizard = $wizardFactory->newRule(Wizard::EXPRESSION); - -$expressionWizard->expression('$C1="USA"') - ->setStyle($greenStyleMoney); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($expressionWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/07_Expression_Comparisons.php#L107 "Conditional Formatting - Sales Grid Expression Comparisons") for the repo. - -![11-15-CF-Expression-Sales-Grid-1.png](./images/11-15-CF-Expression-Sales-Grid-1.png) - -Or we could apply multiple comparisons in the same expression, so to check for all sales for the "USA" region in "Q4", combining them using an Excel `AND()`: -```php -$expressionWizard->expression('AND($C1="USA",$D1="Q4")') - ->setStyle($greenStyleMoney); -``` -This example can also be found in the [code samples](https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/ConditionalFormatting/07_Expression_Comparisons.php#L121 "Conditional Formatting - Sales Grid Expression Comparisons") for the repo. - -![11-16-CF-Expression-Sales-Grid-2.png](./images/11-16-CF-Expression-Sales-Grid-2.png) - -## General Notes - -### Stop If True, and No Format Set - -Normally, Excel continues to check even after it finds a match. To tell it to stop once a match is found, 'stop if true' should be specified: -```php -$conditional->setStopIfTrue(true); -``` - -Sometimes you want a matched cell to just show its unconditional format. This is most useful in conjunction with 'stop if true'. -```php -$conditional->setNoFormatSet(true); -``` - -### Changing the Cell Range - -If you want to apply the same Conditional Rule/Style to several different areas on your spreadsheet, then you can do this using the `setCellRange()` method between calls to `getConditional()`. - -```php -$wizardFactory = new Wizard(); -/** @var Wizard\CellValue $wizard */ -$wizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -// Apply the wizard conditional to cell range A2:A10 -$cellRange = 'A2:A10'; -$conditionalStyles = []; -$wizard->between('$B1', Wizard::VALUE_TYPE_CELL) - ->and('$C1', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); - -$spreadsheet->getActiveSheet() - ->getStyle($wizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Apply the same wizard conditional to cell range E2:E10 -$cellRange = 'E2:E10'; -$wizard->setCellRange($cellRange); -$conditionalStyles = []; -$wizard->between('$B1', Wizard::VALUE_TYPE_CELL) - ->and('$C1', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); - -$spreadsheet->getActiveSheet() - ->getStyle($wizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -``` - -Because we use cell `A1` as the baseline cell for relative references, the Wizard is able to handle the necessary adjustments for cell references and formulae to match the range of cells that it is being applied to when `getConditional()` is called, so it returns the correct expression. - -### Converting a Conditional to a Wizard - -If you already have a `Conditional` object; you can create a Wizard from that Conditional to manipulate it using all the benefits of the Wizard before using that to create a new version of the Conditional: - -```php -$wizard = Wizard\CellValue::fromConditional($conditional, '$A$3:$E$8'); -$wizard->greaterThan(12.5); - -$newConditional = $wizard->getConditional(); -``` -This is ok if you know what type of Conditional you want to convert; but it will throw an Exception if the Conditional is not of an appropriate type (ie. not a `cellIs`). - -If you don't know what type of Conditional it is, then it's better to use the Wizard Factory `fromConditional()` method instead; and then test what type of Wizard object is returned: -```php -$wizard = Wizard::fromConditional($conditional, '$A$3:$E$8'); -if ($wizard instanceof Wizard\CellValue) { - $wizard->greaterThan(12.5); - - $newConditional = $wizard->getConditional(); -} -``` diff --git a/docs/topics/creating-spreadsheet.md b/docs/topics/creating-spreadsheet.md index 3a82623edf..dceafe4b7c 100644 --- a/docs/topics/creating-spreadsheet.md +++ b/docs/topics/creating-spreadsheet.md @@ -20,7 +20,7 @@ Details of the different spreadsheet formats supported, and the options available to read them into a Spreadsheet object are described fully in the [Reading Files](./reading-files.md) document. -```php +``` php $inputFileName = './sampleData/example1.xls'; /** Load $inputFileName to a Spreadsheet object **/ @@ -32,7 +32,7 @@ $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName); If you want to create a new workbook, rather than load one from file, then you simply need to instantiate it as a new Spreadsheet object. -```php +``` php /** Create a new Spreadsheet Object **/ $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); ``` @@ -53,7 +53,7 @@ then you also need to "break" these cyclic references before doing so. PhpSpreadsheet provides the `disconnectWorksheets()` method for this purpose. -```php +``` php $spreadsheet->disconnectWorksheets(); unset($spreadsheet); ``` diff --git a/docs/topics/defined-names.md b/docs/topics/defined-names.md deleted file mode 100644 index d62b06fee2..0000000000 --- a/docs/topics/defined-names.md +++ /dev/null @@ -1,593 +0,0 @@ -# Defined Names - -There are two types of Defined Names in MS Excel and other Spreadsheet formats: Named Ranges and Named Formulae. Between them, they can add a lot of power to your Spreadsheets, but they need to be used correctly. - -Working examples for all the code shown in this document can be found in the `/samples/DefinedNames` folder. - -## Named Ranges - -A Named Range provides a name reference to a cell or a range of cells. You can then reference that cell or cells by that name within a formula. - -As an example, I'll create a simple Calculator that adds Tax to a Price. - -```php -// Set up some basic data -$worksheet - ->setCellValue('A1', 'Tax Rate:') - ->setCellValue('B1', '=19%') - ->setCellValue('A3', 'Net Price:') - ->setCellValue('B3', 12.99) - ->setCellValue('A4', 'Tax:') - ->setCellValue('A5', 'Price including Tax:'); - -// Define named ranges -$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('TAX_RATE', $worksheet, '=$B$1') ); -$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PRICE', $worksheet, '=$B$3') ); - -// Reference that defined name in a formula -$worksheet - ->setCellValue('B4', '=PRICE*TAX_RATE') - ->setCellValue('B5', '=PRICE*(1+TAX_RATE)'); - -echo sprintf( - 'With a Tax Rate of %.2f and a net price of %.2f, Tax is %.2f and the gross price is %.2f', - $worksheet->getCell('B1')->getCalculatedValue(), - $worksheet->getCell('B3')->getValue(), - $worksheet->getCell('B4')->getCalculatedValue(), - $worksheet->getCell('B5')->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/SimpleNamedRange.php` - -This makes formulae in the generated spreadsheet easier to understand when viewing it them MS Excel. Using these Named Ranges (providing meaningful human-readable names for cells) makes the purpose of the formula immediately clear. We don't need to look for cell `B2` to see what it is, the name tells us. - -And, if the Tax Rate changes to 16%, then we only need to change the value in cell `B1` to the new Tax rate (`=16%`), or if we want to calculate the Tax Charges for a different net price, that will immediately be reflected in all the calculations that reference those Named Ranges. No matter whereabouts in the worksheet I used that Named Range, it always references the value in cell `B1`. - -In fact, because we were required to specify a worksheet when we defined the name, that name is available from any worksheet within the spreadsheet, and always means cell `B2` in this worksheet (but see the notes on Named Range Scope below). - -### Absolute Named Ranges - -In the above example, when I define the Named Range values (e.g. `'=$B$1'`), I used a `$` before both the row and the column. This made the Named Range an Absolute Reference. - -Another example: -```php -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named range using an absolute cell reference -$spreadsheet->addNamedRange( new NamedRange('CHARGE_RATE', $worksheet, '=$B$1') ); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", "=B{$row}*CHARGE_RATE"); - $row++; -} -$endRow = $row - 1; - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(B{$startRow}:B{$endRow})") - ->setCellValue("C{$row}", "=SUM(C{$startRow}:C{$endRow})"); - - -echo sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $worksheet->getCell("B{$row}")->getCalculatedValue(), - $worksheet->getCell('B1')->getValue(), - $worksheet->getCell("C{$row}")->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/AbsoluteNamedRange.php` - -Because the Named Range `CHARGE_RATE` is defined as an Absolute cell reference, then it always references cell `B2` no matter where it is referenced in a formula in the spreadsheet. - -### Relative Named Ranges - -The previous example showed a simple timesheet using an Absolute Reference for the Charge Rate, used to calculate our billed charges to client. - -The use of `B{$row}` in our formula (at least it will appear as an actual cell reference in MS Excel if we save the file and open it) requires a bit of mental agility to remember that column `B` is our hours for that day. Why can't we use another Named Range called something like `HOURS_PER_DAY` to make the formula more easily readable and meaningful. - -But if we used an Absolute Named Range for `HOURS_PER_DAY`, then we'd need a different Named Range for each day (`MONDAY_HOURS_PER_DAY`, `TUESDAY_HOURS_PER_DAY`, etc), and a different formula for each day of the week; if we kept a monthly timesheet, we would have to defined a different Named Range for every day of the month... and that's a lot more trouble than it's worth, and quickly becomes unmanageable. - -This is where Relative Named Ranges are very useful. - -```php -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange( new NamedRange('CHARGE_RATE', $worksheet, '=$B$1') ); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange( new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1') ); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", "=HOURS_PER_DAY*CHARGE_RATE"); - $row++; -} -$endRow = $row - 1; - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(B{$startRow}:B{$endRow})") - ->setCellValue("C{$row}", "=SUM(C{$startRow}:C{$endRow})"); - - -echo sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $worksheet->getCell("B{$row}")->getCalculatedValue(), - $worksheet->getCell('B1')->getValue(), - $worksheet->getCell("C{$row}")->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/RelativeNamedRange.php` - -The difference in the cell definition for `HOURS_PER_DAY` (`'=$B1'`) is that we have a `$` in front of the column `B`, but not in front of the row number. The `$` makes the column absolute: no matter where in the worksheet we use this name, it always references column `B`. Without a `$`in front of the row number, we make the row number relative, relative to the row where the name appears in a formula, so it effectively replaces the `1` with its own row number when it executes the calculation. - -When it is used in the formula in row 4, then it references cell `B4`, when it appears in row 5, it references cell `B5`, and so on. Using a Relative Named Range, we can use the same Named Range to refer to cells in different rows (and/or different columns), so we can re-use the same Named Range to refer to different cells relative to the row (or column) where we use them. - ---- - -Named Ranges aren't limited to a single cell, but can point to a range of cells. A common use case might be to provide a series of column totals at the bottom of a dataset. Let's take our timesheet, and modify it just slightly to use a Relative column range for that purpose. - -I won't replicate the entire code from the previous example, because I'm only changing a few lines; but we just replace the block: -```php -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(B{$startRow}:B{$endRow})") - ->setCellValue("C{$row}", "=SUM(C{$startRow}:C{$endRow})"); -``` -with: -```php -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange( new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}") ); - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(COLUMN_DATA_VALUES)") - ->setCellValue("C{$row}", "=SUM(COLUMN_DATA_VALUES)"); -``` -`/samples/DefinedNames/RelativeNamedRange2.php` - -Now that I've specified column as relative in the definition of `COLUMN_DATA_VALUES` with an address of column `A`, and the rows are absolute. When the same Relative Named Range is used in column `B`,it references cells in column `B` rather than `A`; and when it is used in column `C`, it references cells in column `C`. - -While we still have a piece of code (`"=A\${$startRow}:A\${$endRow}"`) that isn't easily human-readable, when we open the generated spreadsheet in MS Excel, the displayed formula in for the cells for the totals is immediately understandable. - -### Named Range Scope - -Whenever we define a Named Range, we are required to specify a worksheet, and that name is then available from any worksheet within the spreadsheet, and always means that cell or cell range in the specified worksheet. - -```php -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50'); - -// Define a global named range on the first worksheet for our Charge Rate -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -// Because it is defined globally, it will still be usable from any worksheet in the spreadsheet -$spreadsheet->addNamedRange( new NamedRange('CHARGE_RATE', $worksheet, '=$B$1') ); - -// Create a second worksheet as our client timesheet -$worksheet = $spreadsheet->addSheet(new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'Client Timesheet')); - -// Define named ranges -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange( new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1') ); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Date') - ->setCellValue('B1', 'Hours') - ->setCellValue('C1', 'Charge'); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 2; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", "=HOURS_PER_DAY*CHARGE_RATE"); - $row++; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange( new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}") ); - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(COLUMN_DATA_VALUES)") - ->setCellValue("C{$row}", "=SUM(COLUMN_DATA_VALUES)"); - -echo sprintf( - 'Worked %.2f hours at a rate of %s - Charge to the client is %.2f', - $worksheet->getCell("B{$row}")->getCalculatedValue(), - $chargeRateCellValue = $spreadsheet - ->getSheetByName($spreadsheet->getNamedRange('CHARGE_RATE')->getWorksheet()->getTitle()) - ->getCell($spreadsheet->getNamedRange('CHARGE_RATE')->getCellsInRange()[0])->getValue(), - $worksheet->getCell("C{$row}")->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/ScopedNamedRange.php` - -Even though `CHARGE_RATE` references a cell on a different worksheet, because is set as global (the default) it is accessible from any worksheet in the spreadsheet. so when we reference it in formulae on the second timesheet worksheet, we are able to access the value from that first worksheet and use it in our calculations. - ---- - -However, a Named Range can be locally scoped so that it is only available when referenced from a specific worksheet, or it can be globally scoped. This means that you can use the same Named Range name with different values on different worksheets. - -Building further on our timesheet, perhaps we use a different worksheet for each client, and we use the same hourly rate when billing most of our clients; but for one particular client (perhaps doing work for a friend) we use a lower rate. - -```php -$clients = [ - 'Client #1 - Full Hourly Rate' => [ - '2020-0-06' => 2.5, - '2020-0-07' => 2.25, - '2020-0-08' => 6.0, - '2020-0-09' => 3.0, - '2020-0-10' => 2.25, - ], - 'Client #2 - Full Hourly Rate' => [ - '2020-0-06' => 1.5, - '2020-0-07' => 2.75, - '2020-0-08' => 0.0, - '2020-0-09' => 4.5, - '2020-0-10' => 3.5, - ], - 'Client #3 - Reduced Hourly Rate' => [ - '2020-0-06' => 3.5, - '2020-0-07' => 2.5, - '2020-0-08' => 1.5, - '2020-0-09' => 0.0, - '2020-0-10' => 1.25, - ], -]; - -foreach ($clients as $clientName => $workHours) { - $worksheet = $spreadsheet->addSheet(new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, $clientName)); - - // Set up some basic data for a timesheet - $worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - ; - - // Define named ranges - // CHARGE_RATE is an absolute cell reference that always points to cell B1 - $spreadsheet->addNamedRange( new NamedRange('CHARGE_RATE', $worksheet, '=$B$1', true) ); - // HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used - $spreadsheet->addNamedRange( new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1', true) ); - - // Populate the Timesheet - $startRow = 4; - $row = $startRow; - foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", "=HOURS_PER_DAY*CHARGE_RATE"); - $row++; - } - $endRow = $row - 1; - - // COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used - $spreadsheet->addNamedRange( new NamedRange('COLUMN_TOTAL', $worksheet, "=A\${$startRow}:A\${$endRow}", true) ); - - ++$row; - $worksheet - ->setCellValue("B{$row}", "=SUM(COLUMN_TOTAL)") - ->setCellValue("C{$row}", "=SUM(COLUMN_TOTAL)"); -} -$spreadsheet->removeSheetByIndex(0); - -// Set the reduced charge rate for our special client -$worksheet - ->setCellValue("B1", 4.5); - -foreach ($spreadsheet->getAllSheets() as $worksheet) { - echo sprintf( - 'Worked %.2f hours for "%s" at a rate of %.2f - Charge to the client is %.2f', - $worksheet->getCell("B{$row}")->getCalculatedValue(), - $worksheet->getTitle(), - $worksheet->getCell('B1')->getValue(), - $worksheet->getCell("C{$row}")->getCalculatedValue() - ), PHP_EOL; -} -``` -`/samples/DefinedNames/ScopedNamedRange2.php` - -Now we are creating three worksheets for each of three different clients. Because each Named Range is linked to a worksheet, we need to create three sets of Named Ranges, so that we don't simply reference the cells on only one of the worksheets; but because we are locally scoping them (note the extra boolean argument used when we define the Named Ranges) we can use the same names on each worksheet, and they will reference the correct cells when we use them in our formulae on that worksheet. - -When Named Ranges are being evaluated, the logic looks first to see if there is a locally scoped Named Range defined for the current worksheet. If there is, then that is the Named Range that will be used in the calculation. If no locally scoped Named Range with that name is found, the logic then looks to see if there is a globally scoped Named Range definition, and will use that if it is found. If no Named Range of the required name is found scoped to the current worksheet, or globally scoped, then a `#NAME` error will be returned. - -## Named Formulae - -A Named Formula is a stored formula, or part of a formula, that can be referenced in cells by name, and re-used in many different places within the spreadsheet. - -As an example, I'll modify the simple Tax Calculator that I created as my example for Named Ranges. - -```php -// Add some Named Formulae -// The first to store our tax rate -$spreadsheet->addNamedFormula(new NamedFormula('TAX_RATE', $worksheet, '=19%')); -// The second to calculate the Tax on a Price value (Note that `PRICE` is defined later as a Named Range) -$spreadsheet->addNamedFormula(new NamedFormula('TAX', $worksheet, '=PRICE*TAX_RATE')); - -// Set up some basic data -$worksheet - ->setCellValue('A1', 'Tax Rate:') - ->setCellValue('B1', '=TAX_RATE') - ->setCellValue('A3', 'Net Price:') - ->setCellValue('B3', 19.99) - ->setCellValue('A4', 'Tax:') - ->setCellValue('A5', 'Price including Tax:'); - -// Define a named range that we can use in our formulae -$spreadsheet->addNamedRange(new NamedRange('PRICE', $worksheet, '=$B$3')); - -// Reference the defined formulae in worksheet formulae -$worksheet - ->setCellValue('B4', '=TAX') - ->setCellValue('B5', '=PRICE+TAX'); - -echo sprintf( - 'With a Tax Rate of %.2f and a net price of %.2f, Tax is %.2f and the gross price is %.2f', - $worksheet->getCell('B1')->getCalculatedValue(), - $worksheet->getCell('B3')->getValue(), - $worksheet->getCell('B4')->getCalculatedValue(), - $worksheet->getCell('B5')->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/SimpleNamedFormula.php` - -There are a few points to note here: - -Firstly. we are actually storing the tax rate in a named formula (`TAX_RATE`) rather than as a cell value. When we display the tax rate in cell `B1`, we are really storing an instruction for MS Excel to evaluate the formula and display the result in that cell. - -Then we are using a Named Formula `TAX` that references both another Named Formula (`TAX_RATE`) and a Named Range (`PRICE`) and executes a calculation using them both (`PRICE * TAX_RATE`). - -Finally, we are using the formula `TAX` in two different contexts. Once to display the tax value (in cell `B4`); and a second time as part of another formula (`PRICE + TAX`) in cell `B5`. - ---- - -Named Formulae aren't just restricted tosimple mathematics, but can include MS EXcel functions as well to provide a lot of flexibility; and they can reference values on other worksheets. - -```php -$worksheet = $spreadsheet->setActiveSheetIndex(0); -setYearlyData($worksheet,'2019', $data2019); -$worksheet = $spreadsheet->addSheet(new Worksheet($spreadsheet)); -setYearlyData($worksheet,'2020', $data2020); -$worksheet = $spreadsheet->addSheet(new Worksheet($spreadsheet)); -setYearlyData($worksheet,'2020', [], 'GROWTH'); - -function setYearlyData(Worksheet $worksheet, string $year, $yearlyData, ?string $title = null) { - // Set up some basic data - $worksheetTitle = $title ?: $year; - $worksheet - ->setTitle($worksheetTitle) - ->setCellValue('A1', 'Month') - ->setCellValue('B1', $worksheetTitle === 'GROWTH' ? 'Growth' : 'Sales') - ->setCellValue('C1', $worksheetTitle === 'GROWTH' ? 'Profit Growth' : 'Margin') - ->setCellValue('A2', Date::stringToExcel("{$year}-01-01")); - for ($row = 3; $row <= 13; ++$row) { - $worksheet->setCellValue("A{$row}", "=NEXT_MONTH"); - } - - if (!empty($yearlyData)) { - $worksheet->fromArray($yearlyData, null, 'B2'); - } else { - for ($row = 2; $row <= 13; ++$row) { - $worksheet->setCellValue("B{$row}", "=GROWTH"); - $worksheet->setCellValue("C{$row}", "=PROFIT_GROWTH"); - } - } - - $worksheet->getStyle('A1:C1') - ->getFont()->setBold(true); - $worksheet->getStyle('A2:A13') - ->getNumberFormat() - ->setFormatCode('mmmm'); - $worksheet->getStyle('B2:C13') - ->getNumberFormat() - ->setFormatCode($worksheetTitle === 'GROWTH' ? '0.00%' : '_-€* #,##0_-'); -} - -// Add some Named Formulae -// The first to store our tax rate -$spreadsheet->addNamedFormula(new NamedFormula('NEXT_MONTH', $worksheet, "=EDATE(OFFSET(\$A1,-1,0),1)")); -$spreadsheet->addNamedFormula(new NamedFormula('GROWTH', $worksheet, "=IF('2020'!\$B1=\"\",\"-\",(('2020'!\$B1/'2019'!\$B1)-1))")); -$spreadsheet->addNamedFormula(new NamedFormula('PROFIT_GROWTH', $worksheet, "=IF('2020'!\$C1=\"\",\"-\",(('2020'!\$C1/'2019'!\$C1)-1))")); - -for ($row = 2; $row<=7; ++$row) { - $month = $worksheet->getCell("A{$row}")->getFormattedValue(); - $growth = $worksheet->getCell("B{$row}")->getFormattedValue(); - $profitGrowth = $worksheet->getCell("C{$row}")->getFormattedValue(); - - echo "Growth for {$month} is {$growth}, with a Profit Growth of {$profitGrowth}", PHP_EOL; -} -``` -`/samples/DefinedNames/CrossWorksheetNamedFormula.php` - -Here we're creating two Named Formulae that both use the `IF()` function, and that compare values on two different worksheets, and calculate the percentage difference between the two. We're also creating a Named Formula that uses the `OFFSET()` function to reference the cell immediately above the current Relative cell reference. - -## Combining Named Ranges and Formulae - -For a slightly more complex example combining Named Ranges and Named Formulae, we can build on our client timesheet. - -```php -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); -// Set up the formula for calculating the daily charge -$spreadsheet->addNamedFormula(new NamedFormula('DAILY_CHARGE', null, '=HOURS_PER_DAY*CHARGE_RATE')); -// Set up the formula for calculating the column totals -$spreadsheet->addNamedFormula(new NamedFormula('COLUMN_TOTALS', null, '=SUM(COLUMN_DATA_VALUES)')); - - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=DAILY_CHARGE'); - ++$row; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange(new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}")); - -++$row; -$worksheet - ->setCellValue("B{$row}", '=COLUMN_TOTALS') - ->setCellValue("C{$row}", '=COLUMN_TOTALS'); - -echo sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $worksheet->getCell("B{$row}")->getCalculatedValue(), - $worksheet->getCell('B1')->getValue(), - $worksheet->getCell("C{$row}")->getCalculatedValue() -), PHP_EOL; -``` -`/samples/DefinedNames/NamedFormulaeAndRanges.php` - -The main point to notice in this example is that you must specify a Worksheet for Named Ranges, but that it isn't required for Named Formulae; in fact, specifying a Worksheet for named Formulae can lead to MS Excel errors when a saved file is opened. Generally, it is far safer to specify a null Worksheet value when creating a Named Formula, unless it references cell values explicitly, or you wish to scope it to that Worksheet. - -It also doesn't matter what order we define our Named Ranges and Formulae, even when some are dependent on others: this only matters when we try to use them in a cell calculation, or when we save the file; and as long as every Defined Name has been defined at that point, then it isn't important. In this case, we couldn't define `COLUMN_DATA_VALUES` until we new the range of rows that it needed to contain; but we could still define the `COLUMN_TOTALS` formula before that. - -## Additional Comments - -### Helper - -In all the examples so far, we have explicitly used the `NamedRange` and `NamedFormula` classes, and the Spreadsheet's `addNamedRange()` and `addNamedFormula()` methods, e.g. -```php -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); -``` -However, this can lead to errors if we accidentally set a formula value for a Named Range, or a range value for a Named Formula. - -As a helper, the DefinedName class provides a static method that can identify whether the value expression is a Range or a Formula, and instantiate the appropriate class. -```php -$this->spreadsheet->addDefinedName( - DefinedName::createInstance('FOO', $this->spreadsheet->getSheetByName('Sheet #2'), '=16%', true) -); -``` - -### Naming Names - -The names that you assign to Defined Name must follow the following set of rules: - - The first character of a name must be one of the following characters: - - letter (including UTF-8 letters) - - underscore (`_`) - - Remaining characters in the name can be - - letters (including UTF-8 letters) - - numbers (including UTF-8 numbers) - - periods (`.`) - - underscore characters (`_`) - - The following are not allowed: - - Space characters are not allowed as part of a name. - - Names can't look like cell addresses, such as A35 or R2C2 - - Names are not case sensitive. For example, `North` and `NORTH` are treated as the same name. - -### Limitations - -PHPSpreadsheet doesn't yet fully validate the names that you use, so it is possible to create a spreadsheet in PHPSpreadsheet that will break when you save and try to open it in MS Excel; or that will break PHPSpreadsheet when they are referenced in a cell. -So please be sensible when creating names, and follow the rules listed above. - ---- - -There is nothing to stop you creating a Defined Name that matches an existing Function name -```php -$spreadsheet->addNamedFormula(new NamedFormula('SUM', $worksheet, '=SUM(A1:E5)')); -``` -And this will work without problems in MS Excel. However, it is not guaranteed to work correctly in PHPSpreadsheet; and will certainly cause confusion for anybody reading it; so it is not recommended. Names exist to give clarity to the person reading the spreadsheet, and a cell containing `=SUM` is even harder to understand (what is it the sum of?) than a cell containing `=SUM(B4:B8)`. Use names that provide meaning, like `SUM_OF_WORKED_HOURS`. - ---- - -You cannot have a Named Range and a Named Formula with the same name, unless they are differently scoped. - ---- - -MS Excel uses some "special tricks" to simulate Relative Named Ranges where the row or column comes before the current row or column, useful if you want to get column totals that don't include the current cell. These "tricks" aren't supported by PHPSpreadsheet, but can be simulated using the `OFFSET()` function in a Named Formula. -In our `RelativeNamedRange2.php` example, we explicitly created the `COLUMN_DATA_VALUES` Named Range using only the rows that we knew should be included, so that we weren't including the current row (where we were displaying the total) and creating a cyclic reference: -```php -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange(new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}")); -``` -We could instead have created a Named Function using `OFFSET()` to specify just the start row, and offset the end row by -1 row: -```php -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -// To avoid including the current row,or having to hard-code the range itself (as we did in the previous example) -// we wrap it in a named formula using the OFFSET() function -$spreadsheet->addNamedFormula(new NamedFormula('COLUMN_DATA_VALUES', $worksheet, "=OFFSET(A\$4:A1, -1, 0)")); -``` -as demonstrated in example `RelativeNamedRangeAsFunction.php`. diff --git a/docs/topics/file-formats.md b/docs/topics/file-formats.md index 7318b13611..d447a2f0bd 100644 --- a/docs/topics/file-formats.md +++ b/docs/topics/file-formats.md @@ -15,7 +15,7 @@ file format that was used by Microsoft Excel™ between versions 95 and 2003. The format is supported (to various extents) by most spreadsheet programs. BIFF files normally have an extension of .xls. Documentation describing the format can be [read online](https://msdn.microsoft.com/en-us/library/cc313154(v=office.12).aspx) -or [downloaded as PDF](https://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/%5BMS-XLS%5D.pdf). +or [downloaded as PDF](http://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/%5BMS-XLS%5D.pdf). ### Xml @@ -32,7 +32,7 @@ Office Open XML SpreadsheetML, and Excel 2010 extended this still further with its new features such as sparklines. These files typically have an extension of .xlsx. This format is based around a zipped collection of eXtensible Markup Language (XML) files. Microsoft Office -Open XML SpreadsheetML is mostly standardized in [ECMA 376](https://www.ecma-international.org/news/TC45_current_work/TC45_available_docs.htm) +Open XML SpreadsheetML is mostly standardized in [ECMA 376](http://www.ecma-international.org/news/TC45_current_work/TC45_available_docs.htm) and ISO 29500. ### Ods @@ -46,7 +46,7 @@ extension of .ods. The published specification for the file format is available from [the OASIS Open Office XML Format Technical Committee web page](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=office). Other information is available from [the OpenOffice.org XML File Format -web page](https://www.openoffice.org/xml/), part of the +web page](http://www.openoffice.org/xml/), part of the OpenOffice.org project. ### Slk @@ -71,7 +71,7 @@ library. ### Csv Comma Separated Value (CSV) file format is a common structuring strategy -for text format files. In CSV files, each line in the file represents a +for text format files. In CSV flies, each line in the file represents a row of data and (within each line of the file) the different data fields (or columns) are separated from one another using a comma (`,`). If a data field contains a comma, then it should be enclosed (typically in @@ -80,8 +80,7 @@ semi-colon (`;`) are used as separators instead of a comma, although other symbols can be used. Because CSV is a text-only format, it doesn't support any data formatting options. -"CSV" is not a single, well-defined format (although see -[RFC 4180](https://www.rfc-editor.org/rfc/rfc4180.html) for +"CSV" is not a single, well-defined format (although see RFC 4180 for one definition that is commonly used). Rather, in practice the term "CSV" refers to any file that: @@ -118,5 +117,5 @@ Wide Web Consortium (W3C). However, in 2000, HTML also became an international standard (ISO/IEC 15445:2000). HTML 4.01 was published in late 1999, with further errata published through 2001. In 2004 development began on HTML5 in the Web Hypertext Application Technology -Working Group (WHATWG), which became a joint deliverable with the W3C in 2008. - +Working Group (WHATWG), which became a joint deliverable with the W3C in +2008. diff --git a/docs/topics/images/08-advanced-borders.png b/docs/topics/images/08-advanced-borders.png deleted file mode 100644 index 047110e731..0000000000 Binary files a/docs/topics/images/08-advanced-borders.png and /dev/null differ diff --git a/docs/topics/images/08-cell-comment-with-image.png b/docs/topics/images/08-cell-comment-with-image.png deleted file mode 100644 index a58c39dac5..0000000000 Binary files a/docs/topics/images/08-cell-comment-with-image.png and /dev/null differ diff --git a/docs/topics/images/10-databar-of-conditional-formatting.png b/docs/topics/images/10-databar-of-conditional-formatting.png deleted file mode 100644 index 10c88f9f77..0000000000 Binary files a/docs/topics/images/10-databar-of-conditional-formatting.png and /dev/null differ diff --git a/docs/topics/images/101-Active-Worksheet-1.png b/docs/topics/images/101-Active-Worksheet-1.png deleted file mode 100644 index bc83dc21b3..0000000000 Binary files a/docs/topics/images/101-Active-Worksheet-1.png and /dev/null differ diff --git a/docs/topics/images/101-Active-Worksheet-2.png b/docs/topics/images/101-Active-Worksheet-2.png deleted file mode 100644 index 765af8515e..0000000000 Binary files a/docs/topics/images/101-Active-Worksheet-2.png and /dev/null differ diff --git a/docs/topics/images/101-Active-Worksheet-Change.png b/docs/topics/images/101-Active-Worksheet-Change.png deleted file mode 100644 index 6aa7daaa3d..0000000000 Binary files a/docs/topics/images/101-Active-Worksheet-Change.png and /dev/null differ diff --git a/docs/topics/images/101-Basic-Spreadsheet-with-Worksheet.png b/docs/topics/images/101-Basic-Spreadsheet-with-Worksheet.png deleted file mode 100644 index b61e0dc84e..0000000000 Binary files a/docs/topics/images/101-Basic-Spreadsheet-with-Worksheet.png and /dev/null differ diff --git a/docs/topics/images/11-01-CF-Simple-Select-Range.png b/docs/topics/images/11-01-CF-Simple-Select-Range.png deleted file mode 100644 index b8cca0cb08..0000000000 Binary files a/docs/topics/images/11-01-CF-Simple-Select-Range.png and /dev/null differ diff --git a/docs/topics/images/11-02-CF-Simple-Tab.png b/docs/topics/images/11-02-CF-Simple-Tab.png deleted file mode 100644 index 1ee9c70c3b..0000000000 Binary files a/docs/topics/images/11-02-CF-Simple-Tab.png and /dev/null differ diff --git a/docs/topics/images/11-03-CF-Simple-CellIs-GreaterThan.png b/docs/topics/images/11-03-CF-Simple-CellIs-GreaterThan.png deleted file mode 100644 index 7408743c26..0000000000 Binary files a/docs/topics/images/11-03-CF-Simple-CellIs-GreaterThan.png and /dev/null differ diff --git a/docs/topics/images/11-04-CF-Simple-CellIs-Value-and-Style.png b/docs/topics/images/11-04-CF-Simple-CellIs-Value-and-Style.png deleted file mode 100644 index 94a9e36950..0000000000 Binary files a/docs/topics/images/11-04-CF-Simple-CellIs-Value-and-Style.png and /dev/null differ diff --git a/docs/topics/images/11-05-CF-Simple-CellIs-Highlighted.png b/docs/topics/images/11-05-CF-Simple-CellIs-Highlighted.png deleted file mode 100644 index 7487ce877e..0000000000 Binary files a/docs/topics/images/11-05-CF-Simple-CellIs-Highlighted.png and /dev/null differ diff --git a/docs/topics/images/11-06-CF-Simple-Cell-Value-Change.png b/docs/topics/images/11-06-CF-Simple-Cell-Value-Change.png deleted file mode 100644 index 2c3124f70c..0000000000 Binary files a/docs/topics/images/11-06-CF-Simple-Cell-Value-Change.png and /dev/null differ diff --git a/docs/topics/images/11-07-CF-Wizard.png b/docs/topics/images/11-07-CF-Wizard.png deleted file mode 100644 index 99325fe8dc..0000000000 Binary files a/docs/topics/images/11-07-CF-Wizard.png and /dev/null differ diff --git a/docs/topics/images/11-08-CF-Absolute-Cell-Reference.png b/docs/topics/images/11-08-CF-Absolute-Cell-Reference.png deleted file mode 100644 index a1816e1f38..0000000000 Binary files a/docs/topics/images/11-08-CF-Absolute-Cell-Reference.png and /dev/null differ diff --git a/docs/topics/images/11-09-CF-Relative-Cell-Reference.png b/docs/topics/images/11-09-CF-Relative-Cell-Reference.png deleted file mode 100644 index 9fdaf5641e..0000000000 Binary files a/docs/topics/images/11-09-CF-Relative-Cell-Reference.png and /dev/null differ diff --git a/docs/topics/images/11-10-CF-Blanks-Example.png b/docs/topics/images/11-10-CF-Blanks-Example.png deleted file mode 100644 index 503ba28d0a..0000000000 Binary files a/docs/topics/images/11-10-CF-Blanks-Example.png and /dev/null differ diff --git a/docs/topics/images/11-11-CF-Errors-Example.png b/docs/topics/images/11-11-CF-Errors-Example.png deleted file mode 100644 index 231d26f547..0000000000 Binary files a/docs/topics/images/11-11-CF-Errors-Example.png and /dev/null differ diff --git a/docs/topics/images/11-12-CF-Simple-Example.png b/docs/topics/images/11-12-CF-Simple-Example.png deleted file mode 100644 index 0dc1f13c7c..0000000000 Binary files a/docs/topics/images/11-12-CF-Simple-Example.png and /dev/null differ diff --git a/docs/topics/images/11-13-CF-Formula-with-Relative-Cell-Reference.png b/docs/topics/images/11-13-CF-Formula-with-Relative-Cell-Reference.png deleted file mode 100644 index 20e46afa32..0000000000 Binary files a/docs/topics/images/11-13-CF-Formula-with-Relative-Cell-Reference.png and /dev/null differ diff --git a/docs/topics/images/11-14-CF-Expression-Example-Odd-Even.png b/docs/topics/images/11-14-CF-Expression-Example-Odd-Even.png deleted file mode 100644 index c32becddf4..0000000000 Binary files a/docs/topics/images/11-14-CF-Expression-Example-Odd-Even.png and /dev/null differ diff --git a/docs/topics/images/11-15-CF-Expression-Sales-Grid-1.png b/docs/topics/images/11-15-CF-Expression-Sales-Grid-1.png deleted file mode 100644 index 0c900b9749..0000000000 Binary files a/docs/topics/images/11-15-CF-Expression-Sales-Grid-1.png and /dev/null differ diff --git a/docs/topics/images/11-16-CF-Expression-Sales-Grid-2.png b/docs/topics/images/11-16-CF-Expression-Sales-Grid-2.png deleted file mode 100644 index 2c56608308..0000000000 Binary files a/docs/topics/images/11-16-CF-Expression-Sales-Grid-2.png and /dev/null differ diff --git a/docs/topics/images/11-17-CF-Text-Contains.png b/docs/topics/images/11-17-CF-Text-Contains.png deleted file mode 100644 index f52a7f769c..0000000000 Binary files a/docs/topics/images/11-17-CF-Text-Contains.png and /dev/null differ diff --git a/docs/topics/images/11-18-CF-Date-Occurring-Examples.png b/docs/topics/images/11-18-CF-Date-Occurring-Examples.png deleted file mode 100644 index 3d9d7cdbbb..0000000000 Binary files a/docs/topics/images/11-18-CF-Date-Occurring-Examples.png and /dev/null differ diff --git a/docs/topics/images/11-19-CF-Duplicates-Uniques-Examples.png b/docs/topics/images/11-19-CF-Duplicates-Uniques-Examples.png deleted file mode 100644 index 3d6b751a99..0000000000 Binary files a/docs/topics/images/11-19-CF-Duplicates-Uniques-Examples.png and /dev/null differ diff --git a/docs/topics/images/11-20-CF-Rule-Order-1.png b/docs/topics/images/11-20-CF-Rule-Order-1.png deleted file mode 100644 index 5dbdd5403a..0000000000 Binary files a/docs/topics/images/11-20-CF-Rule-Order-1.png and /dev/null differ diff --git a/docs/topics/images/11-21-CF-Rule-Order-2.pic2.png b/docs/topics/images/11-21-CF-Rule-Order-2.pic2.png deleted file mode 100644 index d3596a5c5c..0000000000 Binary files a/docs/topics/images/11-21-CF-Rule-Order-2.pic2.png and /dev/null differ diff --git a/docs/topics/images/11-21-CF-Rule-Order-2.pic3.png b/docs/topics/images/11-21-CF-Rule-Order-2.pic3.png deleted file mode 100644 index 996a26d0b4..0000000000 Binary files a/docs/topics/images/11-21-CF-Rule-Order-2.pic3.png and /dev/null differ diff --git a/docs/topics/images/11-21-CF-Rule-Order-2.png b/docs/topics/images/11-21-CF-Rule-Order-2.png deleted file mode 100644 index f874a0b0bc..0000000000 Binary files a/docs/topics/images/11-21-CF-Rule-Order-2.png and /dev/null differ diff --git a/docs/topics/images/12-01-MergeCells-Options-2.png b/docs/topics/images/12-01-MergeCells-Options-2.png deleted file mode 100644 index 5e745fc934..0000000000 Binary files a/docs/topics/images/12-01-MergeCells-Options-2.png and /dev/null differ diff --git a/docs/topics/images/12-01-MergeCells-Options-3.png b/docs/topics/images/12-01-MergeCells-Options-3.png deleted file mode 100644 index 30ad346eac..0000000000 Binary files a/docs/topics/images/12-01-MergeCells-Options-3.png and /dev/null differ diff --git a/docs/topics/images/12-01-MergeCells-Options.png b/docs/topics/images/12-01-MergeCells-Options.png deleted file mode 100644 index 34c8f5e3e6..0000000000 Binary files a/docs/topics/images/12-01-MergeCells-Options.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Array-Formula-2.png b/docs/topics/images/12-CalculationEngine-Array-Formula-2.png deleted file mode 100644 index 45fc3ce5e8..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Array-Formula-2.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Array-Formula-3.png b/docs/topics/images/12-CalculationEngine-Array-Formula-3.png deleted file mode 100644 index 2f01e9d2ae..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Array-Formula-3.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Array-Formula.png b/docs/topics/images/12-CalculationEngine-Array-Formula.png deleted file mode 100644 index 77987b2707..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Array-Formula.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Basic-Formula-2.png b/docs/topics/images/12-CalculationEngine-Basic-Formula-2.png deleted file mode 100644 index 465f27a278..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Basic-Formula-2.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Basic-Formula.png b/docs/topics/images/12-CalculationEngine-Basic-Formula.png deleted file mode 100644 index 03cd82a686..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Basic-Formula.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Spillage-Formula-2.png b/docs/topics/images/12-CalculationEngine-Spillage-Formula-2.png deleted file mode 100644 index 8fc397d1d6..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Spillage-Formula-2.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Spillage-Formula.png b/docs/topics/images/12-CalculationEngine-Spillage-Formula.png deleted file mode 100644 index 4189cb47fa..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Spillage-Formula.png and /dev/null differ diff --git a/docs/topics/images/12-CalculationEngine-Spillage-Operator.png b/docs/topics/images/12-CalculationEngine-Spillage-Operator.png deleted file mode 100644 index c096875e94..0000000000 Binary files a/docs/topics/images/12-CalculationEngine-Spillage-Operator.png and /dev/null differ diff --git a/docs/topics/images/99-Properties_Advanced-Form-2.png b/docs/topics/images/99-Properties_Advanced-Form-2.png deleted file mode 100644 index d047bd554b..0000000000 Binary files a/docs/topics/images/99-Properties_Advanced-Form-2.png and /dev/null differ diff --git a/docs/topics/images/99-Properties_Advanced-Form.png b/docs/topics/images/99-Properties_Advanced-Form.png deleted file mode 100644 index 4c9cfab33c..0000000000 Binary files a/docs/topics/images/99-Properties_Advanced-Form.png and /dev/null differ diff --git a/docs/topics/images/99-Properties_Advanced.png b/docs/topics/images/99-Properties_Advanced.png deleted file mode 100644 index d0eec1e9bc..0000000000 Binary files a/docs/topics/images/99-Properties_Advanced.png and /dev/null differ diff --git a/docs/topics/images/99-Properties_Block.png b/docs/topics/images/99-Properties_Block.png deleted file mode 100644 index e87494f016..0000000000 Binary files a/docs/topics/images/99-Properties_Block.png and /dev/null differ diff --git a/docs/topics/images/99-Properties_File-Menu.png b/docs/topics/images/99-Properties_File-Menu.png deleted file mode 100644 index cc473a6c28..0000000000 Binary files a/docs/topics/images/99-Properties_File-Menu.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 1.png b/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 1.png deleted file mode 100644 index 34bbfb9577..0000000000 Binary files a/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 1.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 2.png b/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 2.png deleted file mode 100644 index 77a898e65e..0000000000 Binary files a/docs/topics/images/Behind the Mask/Accounting Format Wizard - Code 2.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Additional Masking Symbols.png b/docs/topics/images/Behind the Mask/Additional Masking Symbols.png deleted file mode 100644 index b1f567b50b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Additional Masking Symbols.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Basic Masking Symbols.png b/docs/topics/images/Behind the Mask/Basic Masking Symbols.png deleted file mode 100644 index 3417d6be88..0000000000 Binary files a/docs/topics/images/Behind the Mask/Basic Masking Symbols.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Composite - Basic Wizard.png b/docs/topics/images/Behind the Mask/Composite - Basic Wizard.png deleted file mode 100644 index f89da8670b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Composite - Basic Wizard.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Composite - Locale Wizard.png b/docs/topics/images/Behind the Mask/Composite - Locale Wizard.png deleted file mode 100644 index d6691cd8d5..0000000000 Binary files a/docs/topics/images/Behind the Mask/Composite - Locale Wizard.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Conditional 1.png b/docs/topics/images/Behind the Mask/Conditional 1.png deleted file mode 100644 index 39e885d528..0000000000 Binary files a/docs/topics/images/Behind the Mask/Conditional 1.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Conditional 2.png b/docs/topics/images/Behind the Mask/Conditional 2.png deleted file mode 100644 index 4c743c2994..0000000000 Binary files a/docs/topics/images/Behind the Mask/Conditional 2.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Conditional Symbols.png b/docs/topics/images/Behind the Mask/Conditional Symbols.png deleted file mode 100644 index 52db87cbc8..0000000000 Binary files a/docs/topics/images/Behind the Mask/Conditional Symbols.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 1.png b/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 1.png deleted file mode 100644 index 8ce656f390..0000000000 Binary files a/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 1.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 2.png b/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 2.png deleted file mode 100644 index 65cd4e4d70..0000000000 Binary files a/docs/topics/images/Behind the Mask/Currency Format Wizard - Code 2.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Date Format Codes.png b/docs/topics/images/Behind the Mask/Date Format Codes.png deleted file mode 100644 index 068976ff6a..0000000000 Binary files a/docs/topics/images/Behind the Mask/Date Format Codes.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Digit Placeholders.png b/docs/topics/images/Behind the Mask/Digit Placeholders.png deleted file mode 100644 index 357d1d3357..0000000000 Binary files a/docs/topics/images/Behind the Mask/Digit Placeholders.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Duration Format Codes.png b/docs/topics/images/Behind the Mask/Duration Format Codes.png deleted file mode 100644 index 21f708dc7b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Duration Format Codes.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Accounting.png b/docs/topics/images/Behind the Mask/Excel Number Format - Accounting.png deleted file mode 100644 index 70d57e3217..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Accounting.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Currency.png b/docs/topics/images/Behind the Mask/Excel Number Format - Currency.png deleted file mode 100644 index 8c097f097e..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Currency.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Custom.png b/docs/topics/images/Behind the Mask/Excel Number Format - Custom.png deleted file mode 100644 index 50a540add0..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Custom.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Date.png b/docs/topics/images/Behind the Mask/Excel Number Format - Date.png deleted file mode 100644 index 510d4b8b2f..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Date.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Fraction.png b/docs/topics/images/Behind the Mask/Excel Number Format - Fraction.png deleted file mode 100644 index 49db29dea8..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Fraction.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - General.png b/docs/topics/images/Behind the Mask/Excel Number Format - General.png deleted file mode 100644 index eae21f6607..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - General.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Number.png b/docs/topics/images/Behind the Mask/Excel Number Format - Number.png deleted file mode 100644 index d6ad5ae266..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Number.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Percentage.png b/docs/topics/images/Behind the Mask/Excel Number Format - Percentage.png deleted file mode 100644 index cafac8b18b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Percentage.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Scientific.png b/docs/topics/images/Behind the Mask/Excel Number Format - Scientific.png deleted file mode 100644 index b1b5726650..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Scientific.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Special.png b/docs/topics/images/Behind the Mask/Excel Number Format - Special.png deleted file mode 100644 index 1e0550e242..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Special.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Text.png b/docs/topics/images/Behind the Mask/Excel Number Format - Text.png deleted file mode 100644 index b87e0fa811..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Text.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format - Time.png b/docs/topics/images/Behind the Mask/Excel Number Format - Time.png deleted file mode 100644 index 71137b67e1..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format - Time.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Excel Number Format.png b/docs/topics/images/Behind the Mask/Excel Number Format.png deleted file mode 100644 index 6369bc533d..0000000000 Binary files a/docs/topics/images/Behind the Mask/Excel Number Format.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Hiding Values.png b/docs/topics/images/Behind the Mask/Hiding Values.png deleted file mode 100644 index ecafcc9c08..0000000000 Binary files a/docs/topics/images/Behind the Mask/Hiding Values.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Indent.png b/docs/topics/images/Behind the Mask/Indent.png deleted file mode 100644 index 5274215238..0000000000 Binary files a/docs/topics/images/Behind the Mask/Indent.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Mask Sections.gif b/docs/topics/images/Behind the Mask/Mask Sections.gif deleted file mode 100644 index 724634d1ff..0000000000 Binary files a/docs/topics/images/Behind the Mask/Mask Sections.gif and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Mask Sections.png b/docs/topics/images/Behind the Mask/Mask Sections.png deleted file mode 100644 index 04f1efbdb5..0000000000 Binary files a/docs/topics/images/Behind the Mask/Mask Sections.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Number Format Wizard - Code.png b/docs/topics/images/Behind the Mask/Number Format Wizard - Code.png deleted file mode 100644 index 287ce45940..0000000000 Binary files a/docs/topics/images/Behind the Mask/Number Format Wizard - Code.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Padding.png b/docs/topics/images/Behind the Mask/Padding.png deleted file mode 100644 index a5c8546958..0000000000 Binary files a/docs/topics/images/Behind the Mask/Padding.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Percentage Format Wizard - Code.png b/docs/topics/images/Behind the Mask/Percentage Format Wizard - Code.png deleted file mode 100644 index db7af15d20..0000000000 Binary files a/docs/topics/images/Behind the Mask/Percentage Format Wizard - Code.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Reading Cell Format - Code.png b/docs/topics/images/Behind the Mask/Reading Cell Format - Code.png deleted file mode 100644 index ca5a0b5ad8..0000000000 Binary files a/docs/topics/images/Behind the Mask/Reading Cell Format - Code.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Reading Cell Format - Output.png b/docs/topics/images/Behind the Mask/Reading Cell Format - Output.png deleted file mode 100644 index 2265cde7f1..0000000000 Binary files a/docs/topics/images/Behind the Mask/Reading Cell Format - Output.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Reading Cell Values - Code.png b/docs/topics/images/Behind the Mask/Reading Cell Values - Code.png deleted file mode 100644 index d0f60b59bb..0000000000 Binary files a/docs/topics/images/Behind the Mask/Reading Cell Values - Code.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Reading Cell Values - Output.png b/docs/topics/images/Behind the Mask/Reading Cell Values - Output.png deleted file mode 100644 index e4d4048b35..0000000000 Binary files a/docs/topics/images/Behind the Mask/Reading Cell Values - Output.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Right Align.png b/docs/topics/images/Behind the Mask/Right Align.png deleted file mode 100644 index 549b89f324..0000000000 Binary files a/docs/topics/images/Behind the Mask/Right Align.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Scaling Example.png b/docs/topics/images/Behind the Mask/Scaling Example.png deleted file mode 100644 index 4526bf62ca..0000000000 Binary files a/docs/topics/images/Behind the Mask/Scaling Example.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Scientific Format Wizard - Code.png b/docs/topics/images/Behind the Mask/Scientific Format Wizard - Code.png deleted file mode 100644 index 898472528f..0000000000 Binary files a/docs/topics/images/Behind the Mask/Scientific Format Wizard - Code.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Setting a Mask - Code 1.png b/docs/topics/images/Behind the Mask/Setting a Mask - Code 1.png deleted file mode 100644 index 104a8fe04b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Setting a Mask - Code 1.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Setting a Mask - Code 2.png b/docs/topics/images/Behind the Mask/Setting a Mask - Code 2.png deleted file mode 100644 index e2f34d7059..0000000000 Binary files a/docs/topics/images/Behind the Mask/Setting a Mask - Code 2.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Setting a Mask - Code 3.png b/docs/topics/images/Behind the Mask/Setting a Mask - Code 3.png deleted file mode 100644 index eabc1e23ba..0000000000 Binary files a/docs/topics/images/Behind the Mask/Setting a Mask - Code 3.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Setting a Mask - Output 1.png b/docs/topics/images/Behind the Mask/Setting a Mask - Output 1.png deleted file mode 100644 index 40ef6f1348..0000000000 Binary files a/docs/topics/images/Behind the Mask/Setting a Mask - Output 1.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Stock Portfolio.png b/docs/topics/images/Behind the Mask/Stock Portfolio.png deleted file mode 100644 index c364f81a0b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Stock Portfolio.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Stock Portfolio.xlsx b/docs/topics/images/Behind the Mask/Stock Portfolio.xlsx deleted file mode 100644 index 9b51e56f3e..0000000000 Binary files a/docs/topics/images/Behind the Mask/Stock Portfolio.xlsx and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Summary - Still a numeric value.png b/docs/topics/images/Behind the Mask/Summary - Still a numeric value.png deleted file mode 100644 index a2e6dec7bb..0000000000 Binary files a/docs/topics/images/Behind the Mask/Summary - Still a numeric value.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/TEXT Function.png b/docs/topics/images/Behind the Mask/TEXT Function.png deleted file mode 100644 index 1242a8c753..0000000000 Binary files a/docs/topics/images/Behind the Mask/TEXT Function.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Text Single Character Example.png b/docs/topics/images/Behind the Mask/Text Single Character Example.png deleted file mode 100644 index 14356c88ae..0000000000 Binary files a/docs/topics/images/Behind the Mask/Text Single Character Example.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Text Single Character Exceptions.png b/docs/topics/images/Behind the Mask/Text Single Character Exceptions.png deleted file mode 100644 index 99173ca48b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Text Single Character Exceptions.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Text String Example.png b/docs/topics/images/Behind the Mask/Text String Example.png deleted file mode 100644 index 2125f39da0..0000000000 Binary files a/docs/topics/images/Behind the Mask/Text String Example.png and /dev/null differ diff --git a/docs/topics/images/Behind the Mask/Time Format Codes.png b/docs/topics/images/Behind the Mask/Time Format Codes.png deleted file mode 100644 index 321693160b..0000000000 Binary files a/docs/topics/images/Behind the Mask/Time Format Codes.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Empty Rows 2.png b/docs/topics/images/Looping the Loop/Empty Rows 2.png deleted file mode 100644 index 304f1cf3bd..0000000000 Binary files a/docs/topics/images/Looping the Loop/Empty Rows 2.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Empty Rows.png b/docs/topics/images/Looping the Loop/Empty Rows.png deleted file mode 100644 index bfc822eb8c..0000000000 Binary files a/docs/topics/images/Looping the Loop/Empty Rows.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Basic Code.png b/docs/topics/images/Looping the Loop/Iterators Basic Code.png deleted file mode 100644 index ad27487895..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Basic Code.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Empty Row 2.png b/docs/topics/images/Looping the Loop/Iterators Empty Row 2.png deleted file mode 100644 index 5ff7723333..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Empty Row 2.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Empty Row 3.png b/docs/topics/images/Looping the Loop/Iterators Empty Row 3.png deleted file mode 100644 index 2e00a77775..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Empty Row 3.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Empty Row.png b/docs/topics/images/Looping the Loop/Iterators Empty Row.png deleted file mode 100644 index 56b642f94d..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Empty Row.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Existing Only.png b/docs/topics/images/Looping the Loop/Iterators Existing Only.png deleted file mode 100644 index 13584e9f39..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Existing Only.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Memory and Timings.png b/docs/topics/images/Looping the Loop/Iterators Memory and Timings.png deleted file mode 100644 index 248ffae226..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Memory and Timings.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Range 1.png b/docs/topics/images/Looping the Loop/Iterators Range 1.png deleted file mode 100644 index e67af5f1ee..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Range 1.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Range 2.png b/docs/topics/images/Looping the Loop/Iterators Range 2.png deleted file mode 100644 index 20fd1fb147..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Range 2.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Iterators Return Null.png b/docs/topics/images/Looping the Loop/Iterators Return Null.png deleted file mode 100644 index e5afc88cb0..0000000000 Binary files a/docs/topics/images/Looping the Loop/Iterators Return Null.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Summary of Memory Usage and Timings.png b/docs/topics/images/Looping the Loop/Summary of Memory Usage and Timings.png deleted file mode 100644 index c76ad94f05..0000000000 Binary files a/docs/topics/images/Looping the Loop/Summary of Memory Usage and Timings.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/Table with Empty Rows.png b/docs/topics/images/Looping the Loop/Table with Empty Rows.png deleted file mode 100644 index f3986f7707..0000000000 Binary files a/docs/topics/images/Looping the Loop/Table with Empty Rows.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/rangeToArray Basic Code.png b/docs/topics/images/Looping the Loop/rangeToArray Basic Code.png deleted file mode 100644 index 005227ddfa..0000000000 Binary files a/docs/topics/images/Looping the Loop/rangeToArray Basic Code.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/rangeToArray Batch 2.png b/docs/topics/images/Looping the Loop/rangeToArray Batch 2.png deleted file mode 100644 index adc1a36330..0000000000 Binary files a/docs/topics/images/Looping the Loop/rangeToArray Batch 2.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/rangeToArray Batch Memory and Timings.png b/docs/topics/images/Looping the Loop/rangeToArray Batch Memory and Timings.png deleted file mode 100644 index 4942918df3..0000000000 Binary files a/docs/topics/images/Looping the Loop/rangeToArray Batch Memory and Timings.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/rangeToArray Batch.png b/docs/topics/images/Looping the Loop/rangeToArray Batch.png deleted file mode 100644 index 1945b9becd..0000000000 Binary files a/docs/topics/images/Looping the Loop/rangeToArray Batch.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Arguments.png b/docs/topics/images/Looping the Loop/toArray Arguments.png deleted file mode 100644 index c45c96614a..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Arguments.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Basic Code.png b/docs/topics/images/Looping the Loop/toArray Basic Code.png deleted file mode 100644 index cd0eb716ce..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Basic Code.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Break at Empty Row.png b/docs/topics/images/Looping the Loop/toArray Break at Empty Row.png deleted file mode 100644 index 5b25d39d0b..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Break at Empty Row.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Memory and Timings.png b/docs/topics/images/Looping the Loop/toArray Memory and Timings.png deleted file mode 100644 index 68934b9449..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Memory and Timings.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Monthly Sales 2.png b/docs/topics/images/Looping the Loop/toArray Monthly Sales 2.png deleted file mode 100644 index 5f6b7b8381..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Monthly Sales 2.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Monthly Sales.png b/docs/topics/images/Looping the Loop/toArray Monthly Sales.png deleted file mode 100644 index 52fd6999e9..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Monthly Sales.png and /dev/null differ diff --git a/docs/topics/images/Looping the Loop/toArray Skip Empty Rows.png b/docs/topics/images/Looping the Loop/toArray Skip Empty Rows.png deleted file mode 100644 index 95683505d9..0000000000 Binary files a/docs/topics/images/Looping the Loop/toArray Skip Empty Rows.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Date Arithmetic 2.png b/docs/topics/images/The Dating Game/Date Arithmetic 2.png deleted file mode 100644 index c6b73cee2b..0000000000 Binary files a/docs/topics/images/The Dating Game/Date Arithmetic 2.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Date Arithmetic.png b/docs/topics/images/The Dating Game/Date Arithmetic.png deleted file mode 100644 index 9795be70db..0000000000 Binary files a/docs/topics/images/The Dating Game/Date Arithmetic.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Date Code 1.png b/docs/topics/images/The Dating Game/Date Code 1.png deleted file mode 100644 index 02a9c2ec74..0000000000 Binary files a/docs/topics/images/The Dating Game/Date Code 1.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Date Format Codes.png b/docs/topics/images/The Dating Game/Date Format Codes.png deleted file mode 100644 index 068976ff6a..0000000000 Binary files a/docs/topics/images/The Dating Game/Date Format Codes.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Date as a number.png b/docs/topics/images/The Dating Game/Date as a number.png deleted file mode 100644 index 99523ff9a7..0000000000 Binary files a/docs/topics/images/The Dating Game/Date as a number.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Duration Format Codes.png b/docs/topics/images/The Dating Game/Duration Format Codes.png deleted file mode 100644 index 21f708dc7b..0000000000 Binary files a/docs/topics/images/The Dating Game/Duration Format Codes.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Locale.png b/docs/topics/images/The Dating Game/Locale.png deleted file mode 100644 index 0df2c5f5b2..0000000000 Binary files a/docs/topics/images/The Dating Game/Locale.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Locale1.png b/docs/topics/images/The Dating Game/Locale1.png deleted file mode 100644 index 276e22fb13..0000000000 Binary files a/docs/topics/images/The Dating Game/Locale1.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Locale2.png b/docs/topics/images/The Dating Game/Locale2.png deleted file mode 100644 index 42502106a8..0000000000 Binary files a/docs/topics/images/The Dating Game/Locale2.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/StringDateValues.jpg b/docs/topics/images/The Dating Game/StringDateValues.jpg deleted file mode 100644 index 910645e019..0000000000 Binary files a/docs/topics/images/The Dating Game/StringDateValues.jpg and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Time Code 2.png b/docs/topics/images/The Dating Game/Time Code 2.png deleted file mode 100644 index c308d64d0f..0000000000 Binary files a/docs/topics/images/The Dating Game/Time Code 2.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Time Format Codes.png b/docs/topics/images/The Dating Game/Time Format Codes.png deleted file mode 100644 index 321693160b..0000000000 Binary files a/docs/topics/images/The Dating Game/Time Format Codes.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Time as a number.png b/docs/topics/images/The Dating Game/Time as a number.png deleted file mode 100644 index 16901d87f1..0000000000 Binary files a/docs/topics/images/The Dating Game/Time as a number.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Timesheet Code 1.png b/docs/topics/images/The Dating Game/Timesheet Code 1.png deleted file mode 100644 index 99cfd8f2b4..0000000000 Binary files a/docs/topics/images/The Dating Game/Timesheet Code 1.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Timesheet Code 2.png b/docs/topics/images/The Dating Game/Timesheet Code 2.png deleted file mode 100644 index b8e3a24c9d..0000000000 Binary files a/docs/topics/images/The Dating Game/Timesheet Code 2.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Timesheet Code 3.png b/docs/topics/images/The Dating Game/Timesheet Code 3.png deleted file mode 100644 index e1921e3840..0000000000 Binary files a/docs/topics/images/The Dating Game/Timesheet Code 3.png and /dev/null differ diff --git a/docs/topics/images/The Dating Game/Timesheet.png b/docs/topics/images/The Dating Game/Timesheet.png deleted file mode 100644 index d843d7bc3a..0000000000 Binary files a/docs/topics/images/The Dating Game/Timesheet.png and /dev/null differ diff --git a/docs/topics/memory_saving.md b/docs/topics/memory_saving.md index e52a83e414..c7f9a0cbbd 100644 --- a/docs/topics/memory_saving.md +++ b/docs/topics/memory_saving.md @@ -1,6 +1,6 @@ # Memory saving -PhpSpreadsheet uses an average of about 1k per cell (1.6k on 64-bit PHP) in your worksheets, so +PhpSpreadsheet uses an average of about 1k per cell in your worksheets, so large workbooks can quickly use up available memory. Cell caching provides a mechanism that allows PhpSpreadsheet to maintain the cell objects in a smaller size of memory, or off-memory (eg: on disk, in APCu, @@ -9,14 +9,14 @@ workbooks, although at a cost of speed to access cell data. By default, PhpSpreadsheet holds all cell objects in memory, but you can specify alternatives by providing your own -[PSR-16](https://www.php-fig.org/psr/psr-16/) implementation. PhpSpreadsheet keys +[PSR-16](http://www.php-fig.org/psr/psr-16/) implementation. PhpSpreadsheet keys are automatically namespaced, and cleaned up after use, so a single cache instance may be shared across several usage of PhpSpreadsheet or even with other cache usages. To enable cell caching, you must provide your own implementation of cache like so: -```php +``` php $cache = new MyCustomPsr16Implementation(); \PhpOffice\PhpSpreadsheet\Settings::setCache($cache); @@ -44,7 +44,7 @@ usage of PhpSpreadsheet. PhpSpreadsheet does not ship with alternative cache implementation. It is up to you to select the most appropriate implementation for your environment. You -can either implement [PSR-16](https://www.php-fig.org/psr/psr-16/) from scratch, +can either implement [PSR-16](http://www.php-fig.org/psr/psr-16/) from scratch, or use [pre-existing libraries](https://packagist.org/search/?q=psr-16). One such library is [PHP Cache](https://www.php-cache.com/) which diff --git a/docs/topics/migration-from-PHPExcel.md b/docs/topics/migration-from-PHPExcel.md index b8f420f38a..b250790b8a 100644 --- a/docs/topics/migration-from-PHPExcel.md +++ b/docs/topics/migration-from-PHPExcel.md @@ -3,51 +3,26 @@ PhpSpreadsheet introduced many breaking changes by introducing namespaces and renaming some classes. To help you migrate existing project, a tool was written to replace all references to PHPExcel -classes to their new names. But there are also manual changes that +classes to their new names. But they are also manual changes that need to be done. ## Automated tool -[RectorPHP](https://github.com/rectorphp/rector) can be used to automatically migrate your codebase. -Note that this support has been dropped from current releases of rector, -so you need to require an earlier release to do this. -Assuming that your files to be migrated live -in `src/`, you can run the migration like so: +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: -```sh -composer require rector/rector:0.15.10 rector/rector-phpoffice phpoffice/phpspreadsheet --dev - -# this creates rector.php config -vendor/bin/rector init -``` - -Add `PHPOfficeSetList` set to `rector.php` - -```php -declare(strict_types=1); - -use Rector\Config\RectorConfig; -use Rector\PHPOffice\Set\PHPOfficeSetList; - -return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([ - PHPOfficeSetList::PHPEXCEL_TO_PHPSPREADSHEET - ]); -}; -``` - -And run Rector on your code: - -```sh -vendor/bin/rector process src +``` sh +cd /project/to/migrate/src +/project/to/migrate/vendor/phpoffice/phpspreadsheet/bin/migrate-from-phpexcel ``` -For more details, see -[rector-phpoffice](https://github.com/rectorphp/rector-phpoffice). +**Important** The tool will irreversibly modify your sources, be sure to +backup everything, and double check the result before committing. ## Manual changes -RectorPHP should take care of everything, but if somehow it does not work, you can review/apply the following manual changes +In addition to automated changes, a few things need to be migrated manually. ### Renamed readers and writers @@ -82,10 +57,12 @@ IOFactory now relies on classes autoloading. Before: ```php -// Before \PHPExcel_IOFactory::addSearchLocation($type, $location, $classname); +``` -// After +After: + +```php \PhpOffice\PhpSpreadsheet\IOFactory::registerReader($type, $classname); ``` @@ -224,17 +201,13 @@ $writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); ### Rendering charts -When rendering charts for HTML or PDF outputs, the process was simplified. -And, while JpGraph support is still available, -the version distributed via Composer is no longer maintained, -so you would need to install the current version manually. -If you rely on this package, please consider -contributing patches either to JpGraph or another `IRenderer` implementation (a good -candidate might be [CpChart](https://github.com/szymach/c-pchart)). +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. -The package [mitoteam/jpgraph](https://github.com/mitoteam/jpgraph) -is distributed via Composer, and is fully compatible with Jpgraph. -We recommend that it be used for rendering. +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: @@ -251,19 +224,19 @@ After: Require the dependency via composer: ```sh -composer require mitoteam/jpgraph +composer require jpgraph/jpgraph ``` And then: ```php -Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); +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). +[PHP extension ZipArchive](http://php.net/manual/en/book.zip.php). So the following were removed: - `PclZip` @@ -275,7 +248,7 @@ So the following were removed: ### Cell caching Cell caching was heavily refactored to leverage -[PSR-16](https://www.php-fig.org/psr/psr-16/). That means most classes +[PSR-16](http://www.php-fig.org/psr/psr-16/). That means most classes related to that feature were removed: - `PHPExcel_CachedObjectStorage_APC` @@ -300,13 +273,13 @@ Refer to [the new documentation](./memory_saving.md) to see how to migrate. ### Dropped conditionally returned cell -For all the following methods, it is not possible to change the type of -returned value. They will always return the Worksheet and never the Cell or Rule: +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() (*deprecated*) +- Worksheet::setCellValueByColumnAndRow() - Worksheet::setCellValueExplicit() -- Worksheet::setCellValueExplicitByColumnAndRow() (*deprecated*) +- Worksheet::setCellValueExplicitByColumnAndRow() - Worksheet::addRule() Migration would be similar to: @@ -418,19 +391,19 @@ So the code must be adapted with something like: // Before $cell = $worksheet->getCellByColumnAndRow($column, $row); -for ($column = 0; $column < $max; ++$column) { - $worksheet->setCellValueByColumnAndRow($column, $row, 'value'); +for ($column = 0; $column < $max; $column++) { + $worksheet->setCellValueByColumnAndRow($column, $row, 'value ' . $column); } // After -$cell = $worksheet->getCell([$column + 1, $row]); +$cell = $worksheet->getCellByColumnAndRow($column + 1, $row); -for ($column = 1; $column <= $max; ++$column) { - $worksheet->setCellValue([$column, $row], 'value'); +for ($column = 1; $column <= $max; $column++) { + $worksheet->setCellValueByColumnAndRow($column, $row, 'value ' . $column); } ``` -All the following methods are affected, and all are now deprecated (see example above for how to replace them): +All the following methods are affected: - `PHPExcel_Worksheet::cellExistsByColumnAndRow()` - `PHPExcel_Worksheet::freezePaneByColumnAndRow()` diff --git a/docs/topics/reading-and-writing-to-file.md b/docs/topics/reading-and-writing-to-file.md index 8764851b8d..cf58e5494b 100644 --- a/docs/topics/reading-and-writing-to-file.md +++ b/docs/topics/reading-and-writing-to-file.md @@ -1,7 +1,8 @@ # Reading and writing to file As you already know from the [architecture](./architecture.md#readers-and-writers), -reading and writing to a persisted storage is not possible using the base PhpSpreadsheet classes. +reading and writing to a +persisted storage is not possible using the base PhpSpreadsheet classes. For this purpose, PhpSpreadsheet provides readers and writers, which are implementations of `\PhpOffice\PhpSpreadsheet\Reader\IReader` and `\PhpOffice\PhpSpreadsheet\Writer\IWriter`. @@ -32,7 +33,7 @@ You can create a `\PhpOffice\PhpSpreadsheet\Reader\IReader` instance using `\PhpOffice\PhpSpreadsheet\IOFactory` in automatic file type resolving mode using the following code sample: -```php +``` php $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load("05featuredemo.xlsx"); ``` @@ -44,7 +45,7 @@ If you need to set some properties on the reader, (e.g. to only read data, see more about this later), then you may instead want to use this variant: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("05featuredemo.xlsx"); $reader->setReadDataOnly(true); $reader->load("05featuredemo.xlsx"); @@ -54,7 +55,7 @@ You can create a `\PhpOffice\PhpSpreadsheet\Reader\IReader` instance using `\PhpOffice\PhpSpreadsheet\IOFactory` in explicit mode using the following code sample: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); $spreadsheet = $reader->load("05featuredemo.xlsx"); ``` @@ -67,7 +68,7 @@ mode. You can create a `\PhpOffice\PhpSpreadsheet\Writer\IWriter` instance using `\PhpOffice\PhpSpreadsheet\IOFactory`: -```php +``` php $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx"); $writer->save("05featuredemo.xlsx"); ``` @@ -83,7 +84,7 @@ outputting the in-memory spreadsheet to a .xlsx file. You can read an .xlsx file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $spreadsheet = $reader->load("05featuredemo.xlsx"); ``` @@ -93,7 +94,7 @@ $spreadsheet = $reader->load("05featuredemo.xlsx"); You can set the option setReadDataOnly on the reader, to instruct the reader to ignore styling, data validation, … and just read cell data: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $reader->setReadDataOnly(true); $spreadsheet = $reader->load("05featuredemo.xlsx"); @@ -104,7 +105,7 @@ $spreadsheet = $reader->load("05featuredemo.xlsx"); You can set the option setLoadSheetsOnly on the reader, to instruct the reader to only load the sheets with a given name: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]); $spreadsheet = $reader->load("05featuredemo.xlsx"); @@ -121,10 +122,10 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`. The following code will only read row 1 and rows 20 – 30 of any sheet in the Excel file: -```php +``` php class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { return true; @@ -138,18 +139,13 @@ $reader->setReadFilter( new MyReadFilter() ); $spreadsheet = $reader->load("06largescale.xlsx"); ``` -Read Filtering does not renumber cell rows and columns. If you filter to read only rows 100-200, cells that you read will still be numbered A100-A200, not A1-A101. Cells A1-A99 will not be loaded, but if you then try to call `getCell()` for a cell outside your loaded range, then PHPSpreadsheet will create a new cell with a null value. - -Methods such as `toArray()` assume that all cells in a spreadsheet has been loaded from A1, so will return null values for rows and columns that fall outside your filter range: it is recommended that you keep track of the range that your filter has requested, and use `rangeToArray()` instead. - - ### \PhpOffice\PhpSpreadsheet\Writer\Xlsx #### Writing a spreadsheet You can write an .xlsx file using the following code: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); $writer->save("05featuredemo.xlsx"); ``` @@ -160,21 +156,12 @@ By default, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted. You can however disable formula pre-calculation: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); $writer->setPreCalculateFormulas(false); $writer->save("05featuredemo.xlsx"); ``` -**Note** Formulas will still be calculated in any column set to be autosized -even if pre-calculated is set to false - -**Note** Prior to release 3.7.0, the use of this feature will cause Excel to be used in a mode where opening a sheet saved in this manner *might* not automatically recalculate a cell's formula when a cell used it the formula changes. Furthermore, that behavior might be applied to all spreadsheets open at the time. To avoid this behavior, add the following statement after `setPreCalculateFormulas` above: -```php -$writer->setForceFullCalc(false); -``` -Starting with Release 4.0.0, the property's default is changed to `false` and that statement is no longer be required. The property can be set to `null` if the old behavior is needed. - #### Office 2003 compatibility pack Because of a bug in the Office2003 compatibility pack, there can be some @@ -186,32 +173,17 @@ code: $writer->setOffice2003Compatibility(true); $writer->save("05featuredemo.xlsx"); -**Office2003 compatibility option should only be used when needed** because -it disables several Office2007 file format options, resulting in a -lower-featured Office2007 spreadsheet. - -### Form Control Fields - -PhpSpreadsheet offers limited support for Forms Controls (buttons, -checkboxes, etc.). The support is available only for Excel 2007 format, -and is offered solely to allow loading a spreadsheet with such controls -and saving it as a new file. -Support is not available for adding such elements to the spreadsheet, -nor even to locate them to determine their properties -(so you can't modify or delete them). -Modifications to a worksheet with controls are "caveat emptor"; -some modifications will work correctly, -but others are very likely to cause problems, -e.g. adding a comment to the worksheet, -or inserting or deleting rows or columns in a manner that would -cause the controls to change location. +**Office2003 compatibility should only be used when needed** Office2003 +compatibility option should only be used when needed. This option +disables several Office2007 file format options, resulting in a +lower-featured Office2007 spreadsheet when this option is used. ## Excel 5 (BIFF) file format Xls file format is the old Excel file format, implemented in PhpSpreadsheet to provide a uniform manner to create both .xlsx and .xls files. It is basically a modified version of [PEAR -Spreadsheet\_Excel\_Writer](https://pear.php.net/package/Spreadsheet_Excel_Writer), +Spreadsheet\_Excel\_Writer](http://pear.php.net/package/Spreadsheet_Excel_Writer), although it has been extended and has fewer limitations and more features than the old PEAR library. This can read all BIFF versions that use OLE2: BIFF5 (introduced with office 95) through BIFF8, but cannot @@ -230,7 +202,7 @@ PHP. You can read an .xls file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls(); $spreadsheet = $reader->load("05featuredemo.xls"); ``` @@ -240,7 +212,7 @@ $spreadsheet = $reader->load("05featuredemo.xls"); You can set the option setReadDataOnly on the reader, to instruct the reader to ignore styling, data validation, … and just read cell data: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls(); $reader->setReadDataOnly(true); $spreadsheet = $reader->load("05featuredemo.xls"); @@ -251,7 +223,7 @@ $spreadsheet = $reader->load("05featuredemo.xls"); You can set the option setLoadSheetsOnly on the reader, to instruct the reader to only load the sheets with a given name: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls(); $reader->setLoadSheetsOnly(["Sheet 1", "My special sheet"]); $spreadsheet = $reader->load("05featuredemo.xls"); @@ -268,10 +240,10 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`. The following code will only read row 1 and rows 20 to 30 of any sheet in the Excel file: -```php +``` php class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { return true; @@ -291,7 +263,7 @@ $spreadsheet = $reader->load("06largescale.xls"); You can write an .xls file using the following code: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet); $writer->save("05featuredemo.xls"); ``` @@ -311,7 +283,7 @@ spreadsheets via PHP. You can read an Excel 2003 .xml file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xml(); $spreadsheet = $reader->load("05featuredemo.xml"); ``` @@ -327,10 +299,10 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`. The following code will only read row 1 and rows 20 to 30 of any sheet in the Excel file: -```php +``` php class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { return true; @@ -362,7 +334,7 @@ regarding to styling cells and handling large spreadsheets via PHP. You can read an .slk file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Slk(); $spreadsheet = $reader->load("05featuredemo.slk"); ``` @@ -378,10 +350,10 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`. The following code will only read row 1 and rows 20 to 30 of any sheet in the SYLK file: -```php +``` php class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { return true; @@ -407,7 +379,7 @@ Open Office or Libre Office Calc files. You can read an .ods file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Ods(); $spreadsheet = $reader->load("05featuredemo.ods"); ``` @@ -423,10 +395,10 @@ read using the `\PhpOffice\PhpSpreadsheet\Reader\DefaultReadFilter`. The following code will only read row 1 and rows 20 to 30 of any sheet in the Calc file: -```php +``` php class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { return true; @@ -456,22 +428,16 @@ regarding to styling cells, number formatting, ... You can read a .csv file using the following code: -```php -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$spreadsheet = $reader->load('sample.csv'); -``` - -You can also treat a string as if it were the contents of a CSV file as follows: - -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$spreadsheet = $reader->loadSpreadsheetFromString($data); +$spreadsheet = $reader->load("sample.csv"); ``` #### Setting CSV options Often, CSV files are not really "comma separated", or use semicolon (`;`) -as a separator. You can set some options before reading a CSV +as a separator. You can instruct +`\PhpOffice\PhpSpreadsheet\Reader\Csv` some options before reading a CSV file. The separator will be auto-detected, so in most cases it should not be necessary @@ -484,7 +450,7 @@ were created in Microsoft Office Excel the correct input encoding may rather be Windows-1252 (CP1252). Always make sure that the input encoding is set appropriately. -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); $reader->setInputEncoding('CP1252'); $reader->setDelimiter(';'); @@ -493,72 +459,13 @@ $reader->setSheetIndex(0); $spreadsheet = $reader->load("sample.csv"); ``` -You may also let PhpSpreadsheet attempt to guess the input encoding. -It will do so based on a test for BOM (UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, -or UTF-32LE), -or by doing heuristic tests for those encodings, falling back to a -specifiable encoding (default is CP1252) if all of those tests fail. - -```php -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$encoding = \PhpOffice\PhpSpreadsheet\Reader\Csv::guessEncoding('sample.csv'); -// or, e.g. $encoding = \PhpOffice\PhpSpreadsheet\Reader\Csv::guessEncoding( -// 'sample.csv', 'ISO-8859-2'); -$reader->setInputEncoding($encoding); -$reader->setDelimiter(';'); -$reader->setEnclosure(''); -$reader->setSheetIndex(0); - -$spreadsheet = $reader->load('sample.csv'); -``` - -You can also set the reader to guess the encoding -rather than calling guessEncoding directly. In this case, -the user-settable fallback encoding is used if nothing else works. - -```php -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$reader->setInputEncoding(\PhpOffice\PhpSpreadsheet\Reader\Csv::GUESS_ENCODING); -$reader->setFallbackEncoding('ISO-8859-2'); // default CP1252 without this statement -$reader->setDelimiter(';'); -$reader->setEnclosure(''); -$reader->setSheetIndex(0); - -$spreadsheet = $reader->load('sample.csv'); -``` - -The CSV reader will normally not load null strings into the spreadsheet. -To load them: -```php -$reader->setPreserveNullString(true); -``` - -Finally, you can set a callback to be invoked when the constructor is executed, -either through `new Csv()` or `IOFactory::load`, -and have that callback set the customizable attributes to whatever -defaults are appropriate for your environment. - -```php -function constructorCallback(\PhpOffice\PhpSpreadsheet\Reader\Csv $reader): void -{ - $reader->setInputEncoding(\PhpOffice\PhpSpreadsheet\Reader\Csv::GUESS_ENCODING); - $reader->setFallbackEncoding('ISO-8859-2'); - $reader->setDelimiter(','); - $reader->setEnclosure('"'); - // Following represents how Excel behaves better than the default escape character - $reader->setEscapeCharacter(''); -} - -\PhpOffice\PhpSpreadsheet\Reader\Csv::setConstructorCallback('constructorCallback'); -$spreadsheet = \PhpSpreadsheet\IOFactory::load('sample.csv'); -``` #### Read a specific worksheet CSV files can only contain one worksheet. Therefore, you can specify which sheet to read from CSV: -```php +``` php $reader->setSheetIndex(0); ``` @@ -569,42 +476,22 @@ data into an existing `Spreadsheet` object. The following code loads a CSV file into an existing `$spreadsheet` containing some sheets, and imports onto the 6th sheet: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); $reader->setDelimiter(';'); -$reader->setEnclosure('"'); +$reader->setEnclosure(''); $reader->setSheetIndex(5); $reader->loadIntoExisting("05featuredemo.csv", $spreadsheet); ``` -#### Line endings - -Line endings for Unix (`\n`) and Windows (`\r\n`) are supported. - -Support for Mac line endings (`\r`) is deprecated since PHP 8.1, -and is scheduled to remain deprecated for all later PHP8 releases; -PhpSpreadsheet will continue to support them for PHP 8.*. -Support is scheduled to be dropped with PHP 9; -PhpSpreadsheet will then no longer handle CSV files -with Mac line endings correctly. - -You can suppress testing for Mac line endings as follows: -```php -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv(); -$reader->setTestAutoDetect(false); -``` -Starting with Release 4.0.0, the property defaults to `false`, -so the statement above is no longer needed. The old behavior -can be enabled by setting the property to `true`. - ### \PhpOffice\PhpSpreadsheet\Writer\Csv #### Writing a CSV file You can write a .csv file using the following code: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); $writer->save("05featuredemo.csv"); ``` @@ -612,38 +499,26 @@ $writer->save("05featuredemo.csv"); #### Setting CSV options Often, CSV files are not really "comma separated", or use semicolon (`;`) -as a separator. You can set some options before writing a CSV +as a separator. You can instruct +`\PhpOffice\PhpSpreadsheet\Writer\Csv` some options before writing a CSV file: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); $writer->setDelimiter(';'); -$writer->setEnclosure('"'); +$writer->setEnclosure(''); $writer->setLineEnding("\r\n"); $writer->setSheetIndex(0); $writer->save("05featuredemo.csv"); ``` -#### CSV enclosures - -By default, all CSV fields are wrapped in the enclosure character, -which defaults to double-quote. -You can change to use the enclosure character only when required: - -``` php -$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); -$writer->setEnclosureRequired(false); - -$writer->save("05featuredemo.csv"); -``` - #### Write a specific worksheet CSV files can only contain one worksheet. Therefore, you can specify which sheet to write to CSV: -```php +``` php $writer->setSheetIndex(0); ``` @@ -653,7 +528,7 @@ By default, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted. You can however disable formula pre-calculation: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); $writer->setPreCalculateFormulas(false); $writer->save("05featuredemo.csv"); @@ -661,41 +536,12 @@ $writer->save("05featuredemo.csv"); #### Writing UTF-8 CSV files -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, -or if the file starts with the 2 characters 'ID', -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); -$writer->setUseBOM(true); -$writer->save("05featuredemo.csv"); -``` - -#### Writing CSV files with desired encoding - -It can be set to output with the encoding that can be specified by PHP's mb_convert_encoding. -This looks like the following code: - -```php -$writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); -$writer->setUseBOM(false); -$writer->setOutputEncoding('SJIS-WIN'); -$writer->save("05featuredemo.csv"); -``` - -#### Writing CSV files with varying numbers of columns - -A CSV file can have a different number of columns in each row. This -differs from the default behavior when saving as a .csv in Excel, but -can be enabled in PhpSpreadsheet by using the following code: +A CSV file can be marked as UTF-8 by writing a BOM file header. This can +be enabled by using the following code: ``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Csv($spreadsheet); -$writer->setVariableColumns(true); +$writer->setUseBOM(true); $writer->save("05featuredemo.csv"); ``` @@ -711,14 +557,14 @@ to set the characters explicitly as shown below. English users will want to use this before doing the export: -```php +``` php \PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator('.'); \PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator(','); ``` German users will want to use the opposite values. -```php +``` php \PhpOffice\PhpSpreadsheet\Shared\StringHelper::setDecimalSeparator(','); \PhpOffice\PhpSpreadsheet\Shared\StringHelper::setThousandsSeparator('.'); ``` @@ -736,7 +582,6 @@ extension. **HTML limitations** Please note that HTML file format has some limits regarding to styling cells, number formatting, ... -Declared charsets compatible with ASCII in range 00-7F, and UTF-8/16 with BOM are supported. ### \PhpOffice\PhpSpreadsheet\Reader\Html @@ -744,7 +589,7 @@ Declared charsets compatible with ASCII in range 00-7F, and UTF-8/16 with BOM ar You can read an .html or .htm file using the following code: -```php +``` php $reader = new \PhpOffice\PhpSpreadsheet\Reader\Html(); $spreadsheet = $reader->load("05featuredemo.html"); @@ -762,7 +607,7 @@ first worksheet by default. You can write a .htm file using the following code: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); $writer->save("05featuredemo.htm"); @@ -773,7 +618,7 @@ $writer->save("05featuredemo.htm"); HTML files can contain one or more worksheets. If you want to write all sheets into a single HTML file, use the following code: -```php +``` php $writer->writeAllSheets(); ``` @@ -782,7 +627,7 @@ $writer->writeAllSheets(); HTML files can contain one or more worksheets. Therefore, you can specify which sheet to write to HTML: -```php +``` php $writer->setSheetIndex(0); ``` @@ -791,19 +636,19 @@ $writer->setSheetIndex(0); There might be situations where you want to explicitly set the included images root. For example, instead of: - ```html + ``` html ``` You might want to see: -```html +``` html ``` You can use the following code to achieve this result: -```php +``` php $writer->setImagesRoot('http://www.example.com'); ``` @@ -813,7 +658,7 @@ By default, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted. You can however disable formula pre-calculation: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); $writer->setPreCalculateFormulas(false); @@ -833,44 +678,47 @@ 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 +generateHTMLHeader(); -$sty = $writer->generateStyles(false); // do not write -$newstyle = << -$sty -body { - background-color: yellow; +echo $writer->generateHTMLHeader(); +?> + + +?> + +--> -EOF; -echo preg_replace('@@', "$newstyle\n", $hdr); + +generateSheetData(); echo $writer->generateHTMLFooter(); +?> ``` -#### Editing HTML during save via a callback +#### Writing UTF-8 HTML files -You can also add a callback function to edit the generated html -before saving. For example, you could change the gridlines -from a thin solid black line: +A HTML file can be marked as UTF-8 by writing a BOM file header. This +can be enabled by using the following code: ``` php -function changeGridlines(string $html): string -{ - return str_replace('{border: 1px solid black;}', - '{border: 2px dashed red;}', - $html); -} $writer = new \PhpOffice\PhpSpreadsheet\Writer\Html($spreadsheet); -$writer->setEditHtmlCallback('changeGridlines'); -$writer->save($filename); +$writer->setUseBOM(true); + +$writer->save("05featuredemo.htm"); ``` #### Decimal and thousands separators @@ -895,11 +743,11 @@ of different libraries. Currently, the following libraries are supported: -| Library | Downloadable from | PhpSpreadsheet writer | -|---------|-------------------------------------|-----------------------| -| TCPDF | https://github.com/tecnickcom/tcpdf | Tcpdf | -| mPDF | https://github.com/mpdf/mpdf | Mpdf | -| Dompdf | https://github.com/dompdf/dompdf | Dompdf | +Library | Downloadable from | PhpSpreadsheet writer +--------|-------------------------------------|---------------------- +TCPDF | https://github.com/tecnickcom/tcpdf | Tcpdf +mPDF | https://github.com/mpdf/mpdf | Mpdf +Dompdf | https://github.com/dompdf/dompdf | Dompdf The different libraries have different strengths and weaknesses. Some generate better formatted output than others, some are faster or use @@ -909,7 +757,7 @@ own circumstances. You can instantiate a writer with its specific name, like so: -```php +``` php $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Mpdf'); ``` @@ -917,7 +765,7 @@ Or you can register which writer you are using with a more generic name, so you don't need to remember which library you chose, only that you want to write PDF files: -```php +``` php $class = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class; \PhpOffice\PhpSpreadsheet\IOFactory::registerWriter('Pdf', $class); $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf'); @@ -925,8 +773,8 @@ $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Pdf') Or you can instantiate directly the writer of your choice like so: -```php -$writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); +``` php +$writer = \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); ``` #### Custom implementation or configuration @@ -934,7 +782,7 @@ $writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); If you need a custom implementation, or custom configuration, of a supported PDF library. You can extends the PDF library, and the PDF writer like so: -```php +``` php class My_Custom_TCPDF extends TCPDF { // ... @@ -957,9 +805,10 @@ class My_Custom_TCPDF_Writer extends \PhpOffice\PhpSpreadsheet\Writer\Pdf\Tcpdf #### Writing a spreadsheet -Once you have identified the Renderer that you wish to use for PDF generation, you can write a .pdf file using the following code: +Once you have identified the Renderer that you wish to use for PDF +generation, you can write a .pdf file using the following code: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); $writer->save("05featuredemo.pdf"); ``` @@ -969,9 +818,10 @@ first worksheet by default. #### Write all worksheets -PDF files can contain one or more worksheets. If you want to write all sheets into a single PDF file, use the following code: +PDF files can contain one or more worksheets. If you want to write all +sheets into a single PDF file, use the following code: -```php +``` php $writer->writeAllSheets(); ``` @@ -980,39 +830,23 @@ $writer->writeAllSheets(); PDF files can contain one or more worksheets. Therefore, you can specify which sheet to write to PDF: -```php +``` php $writer->setSheetIndex(0); ``` -#### Setting Orientation and PaperSize - -PhpSpreadsheet will attempt to honor the orientation and paper size specified -in the worksheet for each page it prints, if the renderer supports that. However, you can set all pages -to have the same orientation and paper size, e.g. - -```php -$writer->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE); -``` - #### Formula pre-calculation By default, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted. You can however disable formula pre-calculation: -```php +``` php $writer = new \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf($spreadsheet); $writer->setPreCalculateFormulas(false); $writer->save("05featuredemo.pdf"); ``` -#### Editing Pdf during save via a callback - -You can also add a callback function to edit the html used to -generate the Pdf before saving. -[See under Html](#editing-html-during-save-via-a-callback). - #### Decimal and thousands separators See section `\PhpOffice\PhpSpreadsheet\Writer\Csv` how to control the @@ -1028,7 +862,7 @@ page setup properties, headers etc. Here is an example how to open a template file, fill in a couple of fields and save it again: -```php +``` php $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('template.xlsx'); $worksheet = $spreadsheet->getActiveSheet(); @@ -1041,172 +875,3 @@ $writer->save('write.xls'); ``` Notice that it is ok to load an xlsx file and generate an xls file. - -## Generating Excel files from HTML content - -If you are generating an Excel file from pre-rendered HTML content you can do so -automatically using the HTML Reader. This is most useful when you are generating -Excel files from web application content that would be downloaded/sent to a user. - -For example: - -```php -$htmlString = '
- - - - - - - - - -
Hello World
Hello
World
Hello
World
'; - -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Html(); -$spreadsheet = $reader->loadFromString($htmlString); - -$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls'); -$writer->save('write.xls'); -``` - -Suppose you have multiple worksheets you'd like created from html. This can be -accomplished as follows. - -```php -$firstHtmlString = ' - - - -
Hello World
'; -$secondHtmlString = ' - - - -
Hello World
'; - -$reader = new \PhpOffice\PhpSpreadsheet\Reader\Html(); -$spreadsheet = $reader->loadFromString($firstHtmlString); -$reader->setSheetIndex(1); -$spreadhseet = $reader->loadFromString($secondHtmlString, $spreadsheet); - -$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls'); -$writer->save('write.xls'); -``` - -## Reader/Writer Flags - -Some Readers and Writers support special "Feature Flags" that need to be explicitly enabled. -An example of this is Charts in a spreadsheet. By default, when you load a spreadsheet that contains Charts, the charts will not be loaded. If all you want to do is read the data in the spreadsheet, then loading charts is an overhead for both speed of loading and memory usage. -However, there are times when you may want to load any charts in the spreadsheet as well as the data. To do so, you need to tell the Reader explicitly to include Charts. - -```php -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("05featuredemo.xlsx"); -$reader->setIncludeCharts(true); -$reader->load("spreadsheetWithCharts.xlsx"); -``` -Alternatively, you can specify this in the call to load the spreadsheet: -```php -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile("spreadsheetWithCharts.xlsx"); -$reader->load("spreadsheetWithCharts.xlsx", $reader::LOAD_WITH_CHARTS); -``` - -If you wish to use the IOFactory `load()` method rather than instantiating a specific Reader, then you can still pass these flags. - -```php -$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load("spreadsheetWithCharts.xlsx", \PhpOffice\PhpSpreadsheet\Reader\IReader::LOAD_WITH_CHARTS); -``` - -Flags that are available that can be passed to the Reader in this way include: - - - $reader::LOAD_WITH_CHARTS - - $reader::READ_DATA_ONLY - - $reader::IGNORE_EMPTY_CELLS - - $reader::IGNORE_ROWS_WITH_NO_CELLS - -| Readers | LOAD_WITH_CHARTS | READ_DATA_ONLY | IGNORE_EMPTY_CELLS | IGNORE_ROWS_WITH_NO_CELLS | -|----------|------------------|----------------|--------------------|---------------------------| -| Xlsx | YES | YES | YES | YES | -| Xls | NO | YES | YES | NO | -| Xml | NO | NO | NO | NO | -| Ods | NO | YES | NO | NO | -| Gnumeric | NO | YES | NO | NO | -| Html | N/A | N/A | N/A | N/A | -| Slk | N/A | NO | NO | NO | -| Csv | N/A | NO | NO | NO | - -Likewise, when saving a file using a Writer, loaded charts will not be saved unless you explicitly tell the Writer to include them: - -```php -$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); -$writer->setIncludeCharts(true); -$writer->save('mySavedFileWithCharts.xlsx'); -``` - -As with the `load()` method, you can also pass flags in the `save()` method: -```php -$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); -$writer->save('mySavedFileWithCharts.xlsx', \PhpOffice\PhpSpreadsheet\Writer\IWriter::SAVE_WITH_CHARTS); -``` - -Flags that are available that can be passed to the Reader in this way include: - -- $reader::SAVE_WITH_CHARTS -- $reader::DISABLE_PRECALCULATE_FORMULAE - -| Writers | SAVE_WITH_CHARTS | DISABLE_PRECALCULATE_FORMULAE | -|---------|------------------|-------------------------------| -| Xlsx | YES | YES | -| Xls | NO | NO | -| Ods | NO | YES | -| Html | YES | YES | -| Pdf | YES | YES | -| Csv | N/A | YES | - -### Combining Flags - -One benefit of flags is that you can pass several flags in a single method call. -Two or more flags can be passed together using PHP's `|` operator. - -```php -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile('myExampleFile.xlsx'); -$reader->load( - 'spreadsheetWithCharts.xlsx', - $reader::READ_DATA_ONLY | $reader::IGNORE_EMPTY_CELLS -); -``` - -## Writing Data as a Plaintext Grid - -Although not really a spreadsheet format, it can be useful to write data in grid format to a plaintext file. -Code like the following can be used: -```php - $array = $sheet->toArray(null, true, true, true); - $textGrid = new \PhpOffice\PhpSpreadsheet\Shared\TextGrid( - $array, - true, // true for cli, false for html - // Starting with release 4.2, - // the output format can be tweaked by uncommenting - // any of the following 3 optional parameters. - // rowDividers: true, - // rowHeaders: false, - // columnHeaders: false, - ); - $result = $textGrid->render(); -``` -You can then echo `$result` to a terminal, or write it to a file with `file_put_contents`. The result will resemble: -``` - +-----+------------------+---+----------+ - | A | B | C | D | -+---+-----+------------------+---+----------+ -| 1 | 6 | 1900-01-06 00:00 | | 0.572917 | -| 2 | 6 | TRUE | | 1<>2 | -| 3 | xyz | xyz | | | -+---+-----+------------------+---+----------+ -``` -Please note that this may produce sub-optimal results for situations such as: - -- use of accents as combining characters rather than using pre-composed characters (may be handled by extending the class to override the `getString` or `strlen` methods) -- Fullwidth characters -- right-to-left characters (better display in a browser than a terminal on a non-RTL system) -- multi-line strings diff --git a/docs/topics/reading-files.md b/docs/topics/reading-files.md index a7c26f08aa..779082dc85 100644 --- a/docs/topics/reading-files.md +++ b/docs/topics/reading-files.md @@ -22,7 +22,7 @@ The simplest way to load a workbook file is to let PhpSpreadsheet's IO Factory identify the file type and load it, calling the static `load()` method of the `\PhpOffice\PhpSpreadsheet\IOFactory` class. -```php +``` php $inputFileName = './sampleData/example1.xls'; /** Load $inputFileName to a Spreadsheet Object **/ @@ -44,22 +44,6 @@ practise), it will reject the Xls loader that it would normally use for a .xls file; and test the file using the other loaders until it finds the appropriate loader, and then use that to read the file. -If you know that this is an `xls` file, but don't know whether it is a -genuine BIFF-format Excel or Html markup with an xls extension, you can -limit the loader to check only those two possibilities by passing in an -array of Readers to test against. - -```php -$inputFileName = './sampleData/example1.xls'; -$testAgainstFormats = [ - \PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS, - \PhpOffice\PhpSpreadsheet\IOFactory::READER_HTML, -]; - -/** Load $inputFileName to a Spreadsheet Object **/ -$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName, 0, $testAgainstFormats); -``` - While easy to implement in your code, and you don't need to worry about the file type; this isn't the most efficient method to load a file; and it lacks the flexibility to configure the loader in any way before @@ -75,7 +59,7 @@ supported filetype by name. However, you may get unpredictable results if the file isn't of the right type (e.g. it is a CSV with an extension of .xls), although this type of exception should normally be trapped. -```php +``` php $inputFileName = './sampleData/example1.xls'; /** Create a new Xls Reader **/ @@ -97,7 +81,7 @@ Alternatively, you can use the IO Factory's `createReader()` method to instantiate the reader object for you, simply telling it the file type of the reader that you want instantiating. -```php +``` php $inputFileType = 'Xls'; // $inputFileType = 'Xlsx'; // $inputFileType = 'Xml'; @@ -120,13 +104,10 @@ If you're uncertain of the filetype, you can use the `IOFactory::identify()` method to identify the reader that you need, before using the `createReader()` method to instantiate the reader object. -```php +``` php $inputFileName = './sampleData/example1.xls'; -/** - * Identify the type of $inputFileName. - * See below for a possible improvement for release 4.1.0+. - */ +/** Identify the type of $inputFileName **/ $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName); /** Create a new Reader of the type that has been identified **/ $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); @@ -137,128 +118,12 @@ $spreadsheet = $reader->load($inputFileName); See `samples/Reader/04_Simple_file_reader_using_the_IOFactory_to_identify_a_reader_to_use.php` for a working example of this code. -Prior to release 4.1.0, `identify` returns a file type. -It may be more useful to return a fully-qualified class name, -which can be accomplished using a parameter introduced in 4.1.0: -```php -$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName, null, true); -``` - -As with the IOFactory `load()` method, you can also pass an array of formats -for the `identify()` method to check against if you know that it will only -be in a subset of the possible formats that PhpSpreadsheet supports. - -```php -$inputFileName = './sampleData/example1.xls'; -$testAgainstFormats = [ - \PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS, - \PhpOffice\PhpSpreadsheet\IOFactory::READER_HTML, -]; - -/** Identify the type of $inputFileName **/ -$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName, $testAgainstFormats); -``` - -You can also use this to confirm that a file is what it claims to be: - -```php -$inputFileName = './sampleData/example1.xls'; - -try { - /** Verify that $inputFileName really is an Xls file **/ - $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName, [\PhpOffice\PhpSpreadsheet\IOFactory::READER_XLS]); -} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) { - // File isn't actually an Xls file, even though it has an xls extension -} -``` - ## Spreadsheet Reader Options Once you have created a reader object for the workbook that you want to load, you have the opportunity to set additional options before executing the `load()` method. -All of these options can be set by calling the appropriate methods against the Reader (as described below), but some options (those with only two possible values) can also be set through flags, either by calling the Reader's `setFlags()` method, or passing the flags as an argument in the call to `load()`. -Those options that can be set through flags are: - -Option | Flag | Default --------------------|-------------------------------------|------------------------ -Empty Cells | IReader::IGNORE_EMPTY_CELLS | Load empty cells -Rows with no Cells | IReader::IGNORE_ROWS_WITH_NO_CELLS | Load rows with no cells -Data Only | IReader::READ_DATA_ONLY | Read data, structure and style -Charts | IReader::LOAD_WITH_CHARTS | Don't read charts - -Several flags can be combined in a single call: -```php -$inputFileType = 'Xlsx'; -$inputFileName = './sampleData/example1.xlsx'; - -/** Create a new Reader of the type defined in $inputFileType **/ -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); -/** Set additional flags before the call to load() */ -$reader->setFlags(IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS); -$reader->load($inputFileName); -``` -or -```php -$inputFileType = 'Xlsx'; -$inputFileName = './sampleData/example1.xlsx'; - -/** Create a new Reader of the type defined in $inputFileType **/ -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); -/** Set additional flags in the call to load() */ -$reader->load($inputFileName, IReader::IGNORE_EMPTY_CELLS | IReader::LOAD_WITH_CHARTS); -``` - -### Ignoring Empty Cells - -Many Excel files have empty rows or columns at the end of a worksheet, which can't easily be seen when looking at the file in Excel (Try using Ctrl-End to see the last cell in a worksheet). -By default, PhpSpreadsheet will load these cells, because they are valid Excel values; but you may find that an apparently small spreadsheet requires a lot of memory for all those empty cells. -If you are running into memory issues with seemingly small files, you can tell PhpSpreadsheet not to load those empty cells using the `setReadEmptyCells()` method. - -```php -$inputFileType = 'Xls'; -$inputFileName = './sampleData/example1.xls'; - -/** Create a new Reader of the type defined in $inputFileType **/ -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); -/** Advise the Reader that we only want to load cell's that contain actual content **/ -$reader->setReadEmptyCells(false); -/** Load $inputFileName to a Spreadsheet Object **/ -$spreadsheet = $reader->load($inputFileName); -``` - -Note that cells containing formulae will still be loaded, even if that formula evaluates to a NULL or an empty string. -Similarly, Conditional Styling might also hide the value of a cell; but cells that contain Conditional Styling or Data Validation will always be loaded regardless of their value. - -This option is available for the following formats: - -Reader | Y/N |Reader | Y/N |Reader | Y/N | -----------|:---:|--------|:---:|--------------|:---:| -Xlsx | YES | Xls | YES | Xml | NO | -Ods | NO | SYLK | NO | Gnumeric | NO | -CSV | NO | HTML | NO - -This option is also available through flags. - -### Ignoring Rows With No Cells - -Similar to the previous item, you can choose to ignore rows which contain no cells. -This can also help with memory issues. -```php -$inputFileType = 'Xlsx'; -$inputFileName = './sampleData/example1.xlsx'; - -/** Create a new Reader of the type defined in $inputFileType **/ -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); -/** Advise the Reader that we do not want rows with no cells **/ -$reader->setIgnoreRowsWithNoCells(true); -/** Load $inputFileName to a Spreadsheet Object **/ -$spreadsheet = $reader->load($inputFileName); -``` - -This option is available only for Xlsx. It is also available through flags. - ### Reading Only Data from a Spreadsheet File If you're only interested in the cell values in a workbook, but don't @@ -266,7 +131,7 @@ need any of the cell formatting information, then you can set the reader to read only the data values and any formulae from each cell using the `setReadDataOnly()` method. -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example1.xls'; @@ -281,7 +146,7 @@ $spreadsheet = $reader->load($inputFileName); See `samples/Reader/05_Simple_file_reader_using_the_read_data_only_option.php` for a working example of this code. -It is important to note that most Workbooks (and PhpSpreadsheet) store dates +It is important to note that Workbooks (and PhpSpreadsheet) store dates and times as simple numeric values: they can only be distinguished from other numeric values by the format mask that is applied to that cell. When setting read data only to true, PhpSpreadsheet doesn't read the @@ -297,12 +162,10 @@ Reading Only Data from a Spreadsheet File applies to Readers: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | YES | Xls | YES | Xml | YES | -Ods | YES | SYLK | NO | Gnumeric | YES | +Xlsx | YES | Xls | YES | Xml | YES | +Ods | YES | SYLK | NO | Gnumeric | YES | CSV | NO | HTML | NO -This option is also available through flags. - ### Reading Only Named WorkSheets from a File If your workbook contains a number of worksheets, but you are only @@ -313,7 +176,7 @@ in reading. To read a single sheet, you can pass that sheet name as a parameter to the `setLoadSheetsOnly()` method. -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example1.xls'; $sheetname = 'Data Sheet #2'; @@ -332,7 +195,7 @@ for a working example of this code. If you want to read more than just a single sheet, you can pass a list of sheet names as an array parameter to the `setLoadSheetsOnly()` method. -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example1.xls'; $sheetnames = ['Data Sheet #1','Data Sheet #3']; @@ -351,7 +214,7 @@ for a working example of this code. To reset this option to the default, you can call the `setLoadAllSheets()` method. -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example1.xls'; @@ -370,8 +233,8 @@ Reading Only Named WorkSheets from a File applies to Readers: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | YES | Xls | YES | Xml | YES | -Ods | YES | SYLK | NO | Gnumeric | YES | +Xlsx | YES | Xls | YES | Xml | YES | +Ods | YES | SYLK | NO | Gnumeric | YES | CSV | NO | HTML | NO ### Reading Only Specific Columns and Rows from a File (Read Filters) @@ -385,7 +248,7 @@ should be read by the loader. A read filter must implement the whether a workbook cell identified by those arguments should be read or not. -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example1.xls'; $sheetname = 'Data Sheet #3'; @@ -393,10 +256,10 @@ $sheetname = 'Data Sheet #3'; /** Define a Read Filter class implementing \PhpOffice\PhpSpreadsheet\Reader\IReadFilter */ class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Read rows 1 to 7 and columns A to E only if ($row >= 1 && $row <= 7) { - if (in_array($columnAddress,range('A','E'))) { + if (in_array($column,range('A','E'))) { return true; } } @@ -423,7 +286,7 @@ a very specific circumstance (when you only want cells in the range A1:E7 from your worksheet. A generic Read Filter would probably be more useful: -```php +``` php /** Define a Read Filter class implementing \PhpOffice\PhpSpreadsheet\Reader\IReadFilter */ class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { @@ -438,10 +301,10 @@ class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter $this->columns = $columns; } - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Only read the rows and columns that were configured if ($row >= $this->startRow && $row <= $this->endRow) { - if (in_array($columnAddress,$this->columns)) { + if (in_array($column,$this->columns)) { return true; } } @@ -461,11 +324,7 @@ to read and process a large workbook in "chunks": an example of this usage might be when transferring data from an Excel worksheet to a database. -Read Filtering does not renumber cell rows and columns. If you filter to read only rows 100-200, cells that you read will still be numbered A100-A200, not A1-A101. Cells A1-A99 will not be loaded, but if you then try to call `getCell()` for a cell outside your loaded range, then PHPSpreadsheet will create a new cell with a null value. - -Methods such as `toArray()` assume that all cells in a spreadsheet has been loaded from A1, so will return null values for rows and columns that fall outside your filter range: it is recommended that you keep track of the range that your filter has requested, and use `rangeToArray()` instead. - -```php +``` php $inputFileType = 'Xls'; $inputFileName = './sampleData/example2.xls'; @@ -481,7 +340,7 @@ class ChunkReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter $this->endRow = $startRow + $chunkSize; } - public function readCell($columnAddress, $row, $worksheetName = '') { + public function readCell($column, $row, $worksheetName = '') { // Only read the heading row, and the configured rows if (($row == 1) || ($row >= $this->startRow && $row < $this->endRow)) { return true; @@ -518,7 +377,7 @@ Using Read Filters applies to: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | YES | Xls | YES | Xml | YES | +Xlsx | YES | Xls | YES | Xml | YES | Ods | YES | SYLK | NO | Gnumeric | YES | CSV | YES | HTML | NO | | | @@ -534,7 +393,7 @@ the `setSheetIndex()` method of the `$reader`, then use the `loadIntoExisting()` method rather than the `load()` method to actually read the file into that worksheet. -```php +``` php $inputFileType = 'Csv'; $inputFileNames = [ './sampleData/example1.csv', @@ -576,7 +435,7 @@ Combining Multiple Files into a Single Spreadsheet Object applies to: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | NO | Xls | NO | Xml | NO | +Xlsx | NO | Xls | NO | Xml | NO | Ods | NO | SYLK | YES | Gnumeric | NO | CSV | YES | HTML | NO @@ -593,7 +452,7 @@ Class that we defined in [the above section](#reading-only-specific-columns-and- and the `setSheetIndex()` method of the `$reader`, we can split the CSV file across several individual worksheets. -```php +``` php $inputFileType = 'Csv'; $inputFileName = './sampleData/example2.csv'; @@ -653,7 +512,7 @@ Splitting a single loaded file across multiple worksheets applies to: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | NO | Xls | NO | Xml | NO | +Xlsx | NO | Xls | NO | Xml | NO | Ods | NO | SYLK | NO | Gnumeric | NO | CSV | YES | HTML | NO @@ -664,7 +523,7 @@ cannot auto-detect, it will default to the comma. If this does not fit your use-case, you can manually specify a separator by using the `setDelimiter()` method. -```php +``` php $inputFileType = 'Csv'; $inputFileName = './sampleData/example1.tsv'; @@ -693,49 +552,11 @@ Setting CSV delimiter applies to: Reader | Y/N |Reader | Y/N |Reader | Y/N | ----------|:---:|--------|:---:|--------------|:---:| -Xlsx | NO | Xls | NO | Xml | NO | -Ods | NO | SYLK | NO | Gnumeric | NO | -CSV | YES | HTML | NO - - -### Reading formatted Numbers from a CSV File - -Unfortunately, numbers in a CSV file may be formatted as strings. -If that number is a simple integer or float (with a decimal `.` separator) without any thousands separator, then it will be treated as a number. -However, if the value has a thousands separator (e.g. `12,345`), or a decimal separator that isn't a `.` (e.g. `123,45` for a European locale), then it will be loaded as a string with that formatting. -If you want the Csv Reader to convert that value to a numeric when it loads the file, the you need to tell it to do so. The `castFormattedNumberToNumeric()` lets you do this. - -(Assuming that our server is configured with German locale settings: otherwise it may be necessary to call `setlocale()` before loading the file.) -```php -$inputFileType = 'Csv'; -$inputFileName = './sampleData/example1.de.csv'; - -/** It may be necessary to call setlocale() first if this is not your default locale */ -// setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu'); - -/** Create a new Reader of the type defined in $inputFileType **/ -$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); -/** Enable loading numeric values formatted with German , decimal separator and . thousands separator **/ -$reader->castFormattedNumberToNumeric(true); - -/** Load the file to a Spreadsheet Object **/ -$spreadsheet = $reader->load($inputFileName); -``` -This will attempt to load those formatted numeric values as numbers, based on the server's locale settings. - -If you want to load those values as numbers, but also to retain the formatting as a number format mask, then you can pass a boolean `true` as a second argument to the `castFormattedNumberToNumeric()` method to tell the Reader to identify the format masking to use for that value. This option does have an arbitrary limit of 6 decimal places. - -If your Csv file includes other formats for numbers (currencies, scientific format, etc); then you should probably also use the Advanced Value Binder to handle these cases. - -Applies to: - -Reader | Y/N |Reader | Y/N |Reader | Y/N | -----------|:---:|--------|:---:|--------------|:---:| -Xlsx | NO | Xls | NO | Xml | NO | +Xlsx | NO | Xls | NO | Xml | NO | Ods | NO | SYLK | NO | Gnumeric | NO | CSV | YES | HTML | NO -## A Brief Word about the Advanced Value Binder +### A Brief Word about the Advanced Value Binder When loading data from a file that contains no formatting information, such as a CSV file, then data is read either as strings or numbers @@ -764,19 +585,15 @@ it encountered a hyperlink, or HTML markup within a CSV file. So using a Value Binder allows a great deal more flexibility in the loader logic when reading unformatted text files. -```php +``` php +/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/ +\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); + $inputFileType = 'Csv'; $inputFileName = './sampleData/example1.tsv'; $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); $reader->setDelimiter("\t"); - -/** Tell PhpSpreadsheet that we want to use the Advanced Value Binder **/ -// Old method using static property -\PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); -// Preferred method using dynamic property since 3.4.0 -$reader::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); - $spreadsheet = $reader->load($inputFileName); ``` @@ -787,13 +604,10 @@ Loading using a Value Binder applies to: Reader | Y/N |Reader | Y/N |Reader | Y/N ----------|:---:|--------|:---:|--------------|:---: -Xlsx | NO | Xls | NO | Xml | NO -Ods | NO | SYLK | YES | Gnumeric | NO +Xlsx | NO | Xls | NO | Xml | NO +Ods | NO | SYLK | NO | Gnumeric | NO CSV | YES | HTML | YES -Note that you can also use the Binder to determine how PhpSpreadsheet identified datatypes for values when you set a cell value without explicitly setting a datatype. -Value Binders can also be used to set formatting for a cell appropriate to the value. - ## Error Handling Of course, you should always apply some error handling to your scripts @@ -805,7 +619,7 @@ manner. The PhpSpreadsheet Readers throw a `\PhpOffice\PhpSpreadsheet\Reader\Exception`. -```php +``` php $inputFileName = './sampleData/example-1.xls'; try { @@ -832,7 +646,7 @@ whole file. The `listWorksheetNames()` method returns a simple array listing each worksheet name within the workbook: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); $worksheetNames = $reader->listWorksheetNames($inputFileName); @@ -851,9 +665,9 @@ for a working example of this code. ### listWorksheetInfo The `listWorksheetInfo()` method returns a nested array, with each entry -listing the name, dimensions and state for a worksheet: +listing the name and dimensions for a worksheet: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); $worksheetData = $reader->listWorksheetInfo($inputFileName); @@ -865,8 +679,7 @@ foreach ($worksheetData as $worksheet) { echo 'Rows: ', $worksheet['totalRows'], ' Columns: ', $worksheet['totalColumns'], '
'; echo 'Cell Range: A1:', - $worksheet['lastColumnLetter'], $worksheet['totalRows'], '
'; - echo 'Sheet state: ', $worksheet['sheetState']; + $worksheet['lastColumnLetter'], $worksheet['totalRows']; echo ''; } echo ''; diff --git a/docs/topics/recipes.md b/docs/topics/recipes.md index 2398b12731..0b40cf34c7 100644 --- a/docs/topics/recipes.md +++ b/docs/topics/recipes.md @@ -3,14 +3,12 @@ The following pages offer you some widely-used PhpSpreadsheet recipes. Please note that these do NOT offer complete documentation on specific PhpSpreadsheet API functions, but just a bump to get you started. If you -need specific API functions, please refer to the [API documentation](https://phpoffice.github.io/PhpSpreadsheet). +need specific API functions, please refer to the [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master). For example, [setting a worksheet's page orientation and size ](#setting-a-worksheets-page-orientation-and-size) covers setting a page orientation to A4. Other paper formats, like US Letter, are not covered -in this document, but in the PhpSpreadsheet [API documentation](https://phpoffice.github.io/PhpSpreadsheet). - -My apologies if this documentation seems very basic to some of you; but I spend so much time having to provide help lessons in PHP 101 and Excel 101 that I feel I need to provide this level of very simple detail. +in this document, but in the PhpSpreadsheet [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master). ## Setting a spreadsheet's metadata @@ -20,42 +18,12 @@ finding a specific document in a file repository or a document management system. For example Microsoft Sharepoint uses document metadata to search for a specific document in its document lists. -
- Click here for details of Spreadsheet Document Properties - -These are accessed in MS Excel from the "Info" option on the "File" menu: -![99-Properties_File-Menu.png](images%2F99-Properties_File-Menu.png) - -Some of these properties can be edited "in situ" in the Properties Block: -![99-Properties_Block.png](images%2F99-Properties_Block.png) - -For more advanced properties, click on the "Properties" dropdown: -![99-Properties_Advanced.png](images%2F99-Properties_Advanced.png) - -And you will be able to add/edit/delete a lot of different property values. -![99-Properties_Advanced-Form.png](images%2F99-Properties_Advanced-Form.png) - -Properties on the "General", "Statistics" and "Contents" tabs are informational, and cannot be user-defined in Excel itself. -Properties on the "Summary" tab are all string values. - -The "Custom" tab allows you to define your own properties. More information from the Microsoft Documentation can be found [here](https://support.microsoft.com/en-us/office/view-or-change-the-properties-for-an-office-file-21d604c2-481e-4379-8e54-1dd4622c6b75). -![99-Properties_Advanced-Form-2.png](images%2F99-Properties_Advanced-Form-2.png) - -You can select a property name from the dropdown, or type a new name of your choice; select a Type; enter a value; and then click on "Add". -The new property will then be created and displayed in the list at the bottom of the form. +Setting spreadsheet metadata is done as follows: -While "Text", "Number" (can be an integer or a floating point value) and "Yes or No" types are straightforward to add a value, "Date" types are more difficult, and Microsoft provide very little help. -However, you need to enter the date in the format that matches your locale, so an American would enter "7/4/2023 for the 4th of July; but in the UK I would enter "4/7/2023" for the same date. -Although typically recognised as a date elsewhere in MS Excel, the almost universally recognised `2022-12-31` date format is not recognised as valid here. - -
- -Setting spreadsheet metadata in PhpSpreadsheet is done as follows: - -```php +``` php $spreadsheet->getProperties() ->setCreator("Maarten Balliauw") - ->setLastModifiedBy("Mark Baker") + ->setLastModifiedBy("Maarten Balliauw") ->setTitle("Office 2007 XLSX Test Document") ->setSubject("Office 2007 XLSX Test Document") ->setDescription( @@ -65,154 +33,23 @@ $spreadsheet->getProperties() ->setCategory("Test result file"); ``` -You can choose which properties to set or ignore. - -
- Click here for details of Property Getters/Setters - -PhpSpreadsheet provides specific getters/setters for a number of pre-defined properties. - -| Property Name | DataType | Getter/Setter | Notes | -|------------------|-------------------------|----------------------------------------------|-----------------------------------------------------------| -| Creator | string | getCreator()
setCreator() | | -| Last Modified By | string | getLastModifiedBy()
setLastModifiedBy() | | -| Created | float/int
timestamp | getCreated()
setCreated() | Cannot be modified in MS Excel; but is automatically set. | -| Modified | float/int
timestamp | getModified()
setModified() | Cannot be modified in MS Excel; but is automatically set. | -| Title | string | getTitle()
setTitle() | | -| Description | string | getDescription()
setDescription() | | -| Subject | string | getSubject()
setSubject() | | -| Keywords | string | getKeywords()
setKeywords() | | -| Category | string | getCategory()
setCategory() | Not supported in xls files. | -| Company | string | getCompany()
setCompany() | Not supported in xls files. | -| Manager | string | getManager()
setManager() | Not supported in xls files. | -> **Note:** Not all Spreadsheet File Formats support all of these properties. -> For example: "Category", "Company" and "Manager" are not supported in `xls` files. - -
- -
- Click here for details of Custom Properties - -Additionally, PhpSpreadsheet supports the creation and reading of custom properties for those file formats that accept custom properties. -The following methods of the Properties class can be used when working with custom properties. - - `getCustomProperties()`
- Will return an array listing the names of all custom properties that are defined. - - `isCustomPropertySet(string $propertyName)`
- Will return a boolean indicating if the named custom property is defined. - - `getCustomPropertyValue(string $propertyName)`
- Will return the "raw" value of the named custom property; or null if the property doesn't exist. - - `getCustomPropertyType(string $propertyName)`
- Will return the datatype of the named custom property; or null if the property doesn't exist. - - `setCustomProperty(string $propertyName, $propertyValue = '', $propertyType = null)`
- Will let you set (or modify) a custom property. If you don't provide a datatype, then PhpSpreadsheet will attempt to identify the datatype from the value that you set. - -The recognised Property Types are: - -| Constant | Datatype | Value | -|-----------------------------------|----------|-------| -| Properties::PROPERTY_TYPE_BOOLEAN | boolean | b | -| Properties::PROPERTY_TYPE_INTEGER | integer | i | -| Properties::PROPERTY_TYPE_FLOAT | float | f | -| Properties::PROPERTY_TYPE_DATE | date | d | -| Properties::PROPERTY_TYPE_STRING | string | s | - -When reading property types, you might also encounter: - -| Datatype | Value | -|----------|--------------| -| null | null value | -| empty | empty string | -| u | unknown | - -Other more complex types, such as pointers and filetime, are not supported by PhpSpreadsheet; and are discarded when reading a file. - -
- -```php -$spreadsheet->getProperties() - ->setCustomProperty('Editor', 'Mark Baker') - ->setCustomProperty('Version', 1.17) - ->setCustomProperty('Tested', true) - ->setCustomProperty('Test Date', '2021-03-17', Properties::PROPERTY_TYPE_DATE); -``` -> **Warning:** If the datatype for a date is not explicitly used, then it will be treated as a string. - -> **Note:** Although MS Excel doesn't recognise `2022-12-31` as valid date format when entering Custom Date Properties, PhpSpreadsheet will accept it. - ## Setting a spreadsheet's active sheet -A Spreadsheet consists of (very rarely) none, one or more Worksheets. If you have 1 or more Worksheets, then one (and only one) of those Worksheets can be "Active" (viewed or updated) at a time, but there will always be an "Active" Worksheet (unless you explicitly delete all of the Worksheets in the Spreadsheet). - -
- Click here for details about Worksheets - -When you create a new Spreadsheet in MS Excel, it creates the Spreadsheet with a single Worksheet ("Sheet1") - -![101-Basic-Spreadsheet-with-Worksheet.png](images%2F101-Basic-Spreadsheet-with-Worksheet.png) - -and that is the "Active" Worksheet. - -![101-Active-Worksheet-1.png](images%2F101-Active-Worksheet-1.png) +The following line of code sets the active sheet index to the first +sheet: -This is the same as -```php -$spreadsheet = new Spreadsheet(); -$activeWorksheet = $spreadsheet->getActiveSheet(); -``` -in PhpSpreadsheet. - -And you can then write values to Cells in `$activeWorksheet` (`Sheet1`). - -To create a new Worksheet in MS Excel, you click on the "+" button in the Worksheet Tab Bar. MS Excel will then create a new Worksheet ("Sheet2") in the Spreadsheet, and make that the current "Active" Worksheet. - -![101-Active-Worksheet-2.png](images%2F101-Active-Worksheet-2.png) - -Excel always shows the "Active" Worksheet in the Grid, and you can see which Worksheet is "Active" because it is highlighted in the Worksheet Tab Bar at the bottom of the Worksheet Grid. - -This is the same as -```php -$activeWorksheet = $spreadsheet->createSheet(); +``` php +$spreadsheet->setActiveSheetIndex(0); ``` -in PhpSpreadsheet. - -And you can then write values to Cells in `$activeWorksheet` (`Sheet2`). - -
-To switch between Worksheets in MS Excel, you click on the Tab for the Worksheet that you want to be "Active" in the Worksheet Tab Bar. Excel will then set that as the "Active" Worksheet. - -![101-Active-Worksheet-Change.png](images%2F101-Active-Worksheet-Change.png) - -In PhpSpreadsheet, you do this by calling the Spreadsheet's `setActiveSheetIndex()` methods. -Either: - -```php -$activeWorksheet = $spreadsheet->setActiveSheetIndexByName('Sheet1') -``` -using the name/title of the Worksheet that you want as the "Active" Worksheet. +You can also set the active sheet by its name/title -Or: -```php -$activeWorksheet = $spreadsheet->setActiveSheetIndex(0); +``` php +$spreadsheet->setActiveSheetIndexByName('DataSheet') ``` -Where you set the "Active" Worksheet by its position in the Worksheet Tab Bar, with 0 as the first Worksheet, 1 as the second, etc. - -And you can then write values to Cells in `$activeWorksheet` (`Sheet1`) again. - -You don't have to assign the return value from calls to `createSheet()` and `setActiveSheetIndex()` to a variable, but it means that you can call Worksheet methods directly against `$activeWorksheet`, rather than having to call `$spreadsheet->getActiveSheet()` all the time. -And, unlike MS Excel where you can only update Cells in the "Active" Worksheet; PhpSpreadsheet allows you to update Cells in any Worksheet: -```php -// Create a Spreadsheet, with Worksheet Sheet1, which is the Active Worksheet -$spreadsheet = new Spreadsheet(); -// Assign the Active Worksheet (Sheet1) to $worksheet1 -$worksheet1 = $spreadsheet->getActiveSheet(); -// Create a new Worksheet (Sheet2) and make that the Active Worksheet -$worksheet2 = $spreadsheet->createSheet(); - -$worksheet1->setCellValue('A1', 'I am a cell on Sheet1'); -$worksheet2->setCellValue('A1', 'I am a cell on Sheet2'); -``` +will change the currently active sheet to the worksheet called +"DataSheet". ## Write a date or time into a cell @@ -231,12 +68,10 @@ UST. Writing a date value in a cell consists of 2 lines of code. Select the method that suits you the best. Here are some examples: -```php +``` php + // MySQL-like timestamp '2008-12-31' or date string -// Old method using static property \PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); $spreadsheet->getActiveSheet() ->setCellValue('D1', '2008-12-31'); @@ -259,75 +94,29 @@ $spreadsheet->getActiveSheet()->getStyle('D1') ->getNumberFormat() ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_YYYYMMDDSLASH); ``` + The above methods for entering a date all yield the same result. +`\PhpOffice\PhpSpreadsheet\Style\NumberFormat` provides a lot of +pre-defined date formats. + The `\PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel()` method will also -work with a PHP DateTime object; or with strings containing different well-recognised date formats -(although this is limited in the same ways as using the Advanced Value Binder). +work with a PHP DateTime object. Similarly, times (or date and time values) can be entered in the same fashion: just remember to use an appropriate format code. -> **Note:** See section "Using value binders to facilitate data entry" to learn more +**Note:** + +See section "Using value binders to facilitate data entry" to learn more about the AdvancedValueBinder used in the first example. Excel can also operate in a 1904-based calendar (default for workbooks saved on Mac). Normally, you do not have to worry about this when using PhpSpreadsheet. -`\PhpOffice\PhpSpreadsheet\Style\NumberFormat` provides a number of -pre-defined date formats; but this is just a string value, and you can -define your own values as long as they are a valid MS Excel format. -PhpSpreadsheet also provides a number of Wizards to help you create -Date, Time and DateTime format masks. - -
- Click here for an example of the Date/Time Wizards - -```php -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Date as DateWizard; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Time as TimeWizard; -use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\DateTime as DateTimeWizard; - -$spreadsheet->getActiveSheet()->setCellValue('A1', '=NOW()') -$spreadsheet->getActiveSheet()->setCellValue('A2', '=NOW()') -$spreadsheet->getActiveSheet()->setCellValue('A3', '=NOW()') - -// yyyy-mm-dd -$dateFormat = new DateWizard( - DateWizard::SEPARATOR_DASH, - DateWizard::YEAR_FULL, - DateWizard::MONTH_NUMBER_LONG, - DateWizard::DAY_NUMBER_LONG -); - -$spreadsheet->getActiveSheet()->getStyle('A1') - ->getNumberFormat() - ->setFormatCode($dateFormat); - -// hh:mm -$timeFormat = new TimeWizard( - TimeWizard::SEPARATOR_COLON, - TimeWizard::HOURS_LONG, - TimeWizard::MINUTES_LONG, -); - -$spreadsheet->getActiveSheet()->getStyle('A2') - ->getNumberFormat() - ->setFormatCode($timeFormat); - -// yyyy-mm-dd hh:mm -$dateTimeFormat = new DateTimeWizard(' ', $dateFormat, $timeFormat); - -$spreadsheet->getActiveSheet()->getStyle('A3') - ->getNumberFormat() - ->setFormatCode($dateTimeFormat); -``` - -
- ## Write a formula into a cell Inside the Excel file, formulas are always stored as they would appear in an English version of Microsoft Office Excel, and PhpSpreadsheet -handles all formulas internally in this format. This means that the +handles all formulae internally in this format. This means that the following rules hold: - Decimal separator is `.` (period) @@ -347,14 +136,14 @@ The following line of code writes the formula formula must start with `=` to make PhpSpreadsheet recognise this as a formula. -```php +``` php $spreadsheet->getActiveSheet()->setCellValue('B8','=IF(C4>500,"profit","loss")'); ``` If you want to write a string beginning with an `=` character to a cell, then you should use the `setCellValueExplicit()` method. -```php +``` php $spreadsheet->getActiveSheet() ->setCellValueExplicit( 'B8', @@ -365,164 +154,24 @@ $spreadsheet->getActiveSheet() A cell's formula can be read again using the following line of code: -```php +``` php $formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue(); ``` If you need the calculated value of a cell, use the following code. This is further explained in [the calculation engine](./calculation-engine.md). -```php +``` php $value = $spreadsheet->getActiveSheet()->getCell('B8')->getCalculatedValue(); ``` -### Array Formulas - -With version 3.0.0 of PhpSpreadsheet, we've introduced support for Excel "array formulas". -**It is an opt-in feature.** You need to enable it with the following code: -```php -// preferred method -\PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance($spreadsheet) - ->setInstanceArrayReturnType( - \PhpOffice\PhpSpreadsheet\Calculation\Calculation::RETURN_ARRAY_AS_ARRAY); -// or less preferred -\PhpOffice\PhpSpreadsheet\Calculation\Calculation::setArrayReturnType( - \PhpOffice\PhpSpreadsheet\Calculation\Calculation::RETURN_ARRAY_AS_ARRAY); -``` -This is not a new constant, and setArrayReturnType is also not new, but it has till now not had much effect. -The instance variable set by the new setInstanceArrayReturnType -will always be checked first, and the static variable used only if the instance variable is uninitialized. - -As a basic example, let's look at a receipt for buying some fruit: - -![12-CalculationEngine-Basic-Formula.png](./images/12-CalculationEngine-Basic-Formula.png) - -We can provide a "Cost" formula for each row of the receipt by multiplying the "Quantity" (column `B`) by the "Price" (column `C`); so for the "Apples" in row `2` we enter the formula `=$B2*$C2`. In PhpSpreadsheet, we would set this formula in cell `D2` using: -```php -$spreadsheet->getActiveSheet()->setCellValue('D2','=$B2*$C2'); -``` -and then do the equivalent for rows `3` to `6`. - -To calculate the "Total", we would use a different formula, telling it to calculate the sum value of rows 2 to 6 in the "Cost" column: - -![12-CalculationEngine-Basic-Formula-2.png](./images/12-CalculationEngine-Basic-Formula-2.png) - -I'd imagine that most developers are familiar with this: we're setting a formula that uses an Excel function (the `SUM()` function) and specifying a range of cells to include in the sum (`$D$2:$D6`) -```php -$spreadsheet->getActiveSheet()->setCellValue('D7','=SUM($D$2:$D6'); -``` -However, we could have specified an alternative formula to calculate that result, using the arrays of the "Quantity" and "Cost" columns multiplied directly, and then summed together: - -![12-CalculationEngine-Array-Formula.png](./images/12-CalculationEngine-Array-Formula.png) - -Entering the formula `=SUM(B2:B6*C2:C6)` will calculate the same result; but because it's using arrays, we need to enter it as an "array formula". In MS Excel itself, we'd do this by using `Ctrl-Shift-Enter` rather than simply `Enter` when we define the formula in the formula edit box. MS Excel then shows that this is an array formula in the formula edit box by wrapping it in the `{}` braces (you don't enter these in the formula yourself; MS Excel does it). - -**In recent releases of Excel, Ctrl-Shift-Enter is not required, and Excel does not add the braces. -PhpSpreadsheet will attempt to behave like the recent releases.** - -Or to identify the biggest increase in like-for-like sales from one month to the next: - -![12-CalculationEngine-Array-Formula-3.png](./images/12-CalculationEngine-Array-Formula-3.png) -```php -$spreadsheet->getActiveSheet()->setCellValue('F1','=MAX(B2:B6-C2:C6)'); -``` -Which tells us that the biggest increase in sales between December and January was 30 more (in this case, 30 more Lemons). - ---- - -These are examples of array formula where the results are displayed in a single cell; but other array formulas might be displayed across several cells. -As an example, consider transposing a grid of data: MS Excel provides the `TRANSPOSE()` function for that purpose. Let's transpose our shopping list for the fruit: - -![12-CalculationEngine-Array-Formula-2.png](./images/12-CalculationEngine-Array-Formula-2.png) - -When we do this in MS Excel, we used to need to indicate ___all___ the cells that will contain the transposed data from cells `A1` to `D7`. We do this by selecting the cells where we want to display our transposed data either by holding the left mouse button down while we move with the mouse, or pressing `Shift` and using the arrow keys. -Once we've selected all the cells to hold our data, then we enter the formula `TRANSPOSE(A1:D7)` in the formula edit box, remembering to use `Ctrl-Shift-Enter` to tell MS Excel that this is an array formula. In recent Excel, you can just enter `=TRANSPOSE(A1:D7)` into cell A10. - -Note also that we still set this as the formula for the top-left cell of that range, cell `A10`. - -Simply setting an array formula in a cell and specifying the range won't populate the spillage area for that formula. -```php -$spreadsheet->getActiveSheet() - ->setCellValue( - 'A10', - '=SEQUENCE(3,3)' - ); -// Will return a null, because the formula for A1 hasn't been calculated to populate the spillage area -$result = $spreadsheet->getActiveSheet()->getCell('C3')->getValue(); -``` -To do that, we need to retrieve the calculated value for the cell. -```php -$spreadsheet->getActiveSheet()->getCell('A1')->getCalculatedValue(); -// Will return 9, because the formula for A1 has now been calculated, and the spillage area is populated -$result = $spreadsheet->getActiveSheet()->getCell('C3')->getValue(); -``` -If returning arrays has been enabled, `getCalculatedValue` will return an array when appropriate, and will populate the spill range. If returning arrays has not been enabled, when we call `getCalculatedValue()` for a cell that contains an array formula, PhpSpreadsheet will return the single value from the topmost leftmost cell, and will leave other cells unchanged. -```php -// Will return integer 1, the value for that cell within the array -$a1result = $spreadsheet->getActiveSheet()->getCell('A1')->getCalculatedValue(); -``` - ---- - -Excel365 introduced a number of new functions that return arrays of results. -These include the `UNIQUE()`, `SORT()`, `SORTBY()`, `FILTER()`, `SEQUENCE()` and `RANDARRAY()` functions. -While not all of these have been implemented by the Calculation Engine in PhpSpreadsheet, so they cannot all be calculated within your PHP applications, they can still be read from and written to Xlsx files. - -The `SEQUENCE()` function generates a series of values (in this case, starting with `-10` and increasing in steps of `2.5`); and here we're telling the formula to populate a 3x3 grid with these values. - -![12-CalculationEngine-Spillage-Formula.png](./images/12-CalculationEngine-Spillage-Formula.png) - -Note that this is visually different from using `Ctrl-Shift-Enter` for the formula. When we are positioned in the "spill" range for the grid, MS Excel highlights the area with a blue border; and the formula displayed in the formula editing field isn't wrapped in braces (`{}`). - -And if we select any other cell inside the "spill" area other than the top-left cell, the formula in the formula edit field is greyed rather than displayed in black. - -![12-CalculationEngine-Spillage-Formula-2.png](./images/12-CalculationEngine-Spillage-Formula-2.png) - -When we enter this formula in MS Excel, we don't need to select the range of cells that it should occupy; nor do we need to enter it using `Ctrl-Shift-Enter`. - -### The Spill Operator - -If you want to reference the entire spillage range of an array formula within another formula, you could do so using the standard Excel range operator (`:`, e.g. `A1:C3`); but you may not always know the range, especially for array functions that spill across as many cells as they need, like `UNIQUE()` and `FILTER()`. -To simplify this, MS Excel has introduced the "Spill" Operator (`#`). - -![12-CalculationEngine-Spillage-Operator.png](./images/12-CalculationEngine-Spillage-Operator.png) - -Using our `SEQUENCE()`example, where the formula cell is `A1` and the result spills across the range `A1:C3`, we can use the Spill operator `A1#` to reference all the cells in that spillage range. -In this case, we're taking the absolute value of each cell in that range, and adding them together using the `SUM()` function to give us a result of 50. - -PhpSpreadsheet supports entry of a formula like this using the Spill operator. Alternatively, MS Excel internally implements the Spill Operator as a function (`ANCHORARRAY()`). MS Excel itself doesn't allow you to use this function in a formula, you have to use the "Spill" operator; but PhpSpreadsheet does allow you to use this internal Excel function. PhpSpreadsheet will convert the spill operator to ANCHORARRAY on write (so it may appear that your formula has changed, but it hasn't really); it is not necessary to convert it back on read. - -To create this same function in PhpSpreadsheet, use: -```php -$spreadsheet->getActiveSheet()->setCellValue('D1','=SUM(ABS(ANCHORARRAY(A1)))'); -``` - -When the file is saved, and opened in MS Excel, it will be rendered correctly. - -### The At-sign Operator - -If you want to reference just the first cell of an array formula within another formula, you could do so by prefixing it with an at-sign. You can also select the entry in a range which matches the current row in this way; so, if you enter `=@A1:A5` in cell G3, the result will be the value from A3. MS Excel again implements this under the covers by converting to a function SINGLE. PhpSpreadsheet allows the use of the SINGLE function. It does not yet support the at-sign operator, which can have a different meaning in other contexts. - -### Updating Cell in Spill Area - -Excel prevents you from updating a cell in the spill area. PhpSpreadsheet does not - it seems like it might be quite expensive, needing to reevaluate the entire worksheet with each `setValue`. PhpSpreadsheet does provide a method to be used prior to calling `setValue` if desired. -```php -$sheet->setCellValue('A1', '=SORT{7;5;1}'); -$sheet->getCell('A1')->getCalculatedValue(); // populates A1-A3 -$sheet->isCellInSpillRange('A2'); // true -$sheet->isCellInSpillRange('A3'); // true -$sheet->isCellInSpillRange('A4'); // false -$sheet->isCellInSpillRange('A1'); // false -``` -The last result might be surprising. Excel allows you to alter the formula cell itself, so `isCellInSpillRange` treats the formula cell as not in range. It should also be noted that, if array returns are not enabled, `isCellInSpillRange` will always return `false`. - -## Locale Settings for Formulas +## Locale Settings for Formulae Some localisation elements have been included in PhpSpreadsheet. You can set a locale by changing the settings. To set the locale to Russian you would use: -```php +``` php $locale = 'ru'; $validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale); if (!$validLocale) { @@ -536,29 +185,28 @@ will return an error, and English settings will be used throughout. Once you have set a locale, you can translate a formula from its internal English coding. -```php +``` php $formula = $spreadsheet->getActiveSheet()->getCell('B8')->getValue(); -$translatedFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->translateFormulaToLocale($formula); +$translatedFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->_translateFormulaToLocale($formula); ``` You can also create a formula using the function names and argument separators appropriate to the defined locale; then translate it to English before setting the cell value: -```php +``` php $formula = '=ДÐЕЙ360(ДÐТÐ(2010;2;5);ДÐТÐ(2010;12;31);ИСТИÐÐ)'; $internalFormula = \PhpOffice\PhpSpreadsheet\Calculation\Calculation::getInstance()->translateFormulaToEnglish($formula); $spreadsheet->getActiveSheet()->setCellValue('B8',$internalFormula); ``` Currently, formula translation only translates the function names, the -constants TRUE and FALSE (and NULL), Excel error messages, and the function argument separators. Cell addressing using R1C1 formatting is not supported. +constants TRUE and FALSE, and the function argument separators. At present, the following locale settings are supported: Language | | Locale Code ---------------------|----------------------|------------- -Bulgarian | българÑки | bg Czech | CeÅ¡tina | cs Danish | Dansk | da German | Deutsch | de @@ -568,7 +216,7 @@ French | Français | fr Hungarian | Magyar | hu Italian | Italiano | it Dutch | Nederlands | nl -Norwegian | Norsk BokmÃ¥l | nb +Norwegian | Norsk | no Polish | Jezyk polski | pl Portuguese | Português | pt Brazilian Portuguese | Português Brasileiro | pt_br @@ -576,8 +224,6 @@ Russian | руÑÑкий Ñзык | ru Swedish | Svenska | sv Turkish | Türkçe | tr -If anybody can provide translations for additional languages, particularly Basque (Euskara), Catalan (Català), Croatian (Hrvatski jezik), Galician (Galego), Greek (Ελληνικά), Slovak (SlovenÄina) or Slovenian (SlovenÅ¡Äina); please feel free to volunteer your services, and we'll happily show you what is needed to contribute a new language. - ## Write a newline character "\n" in a cell (ALT+"Enter") In Microsoft Office Excel you get a line break in a cell by hitting @@ -586,7 +232,7 @@ the cell. Here is how to achieve this in PhpSpreadsheet: -```php +``` php $spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld"); $spreadsheet->getActiveSheet()->getStyle('A1')->getAlignment()->setWrapText(true); ``` @@ -601,11 +247,8 @@ AdvancedValuebinder.php automatically turns on "wrap text" for the cell when it sees a newline character in a string that you are inserting in a cell. Just like Microsoft Office Excel. Try this: -```php -// Old method using static property +``` php \PhpOffice\PhpSpreadsheet\Cell\Cell::setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); -// Preferred method using dynamic property since 3.4.0 -$spreadsheet->setValueBinder( new \PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder() ); $spreadsheet->getActiveSheet()->getCell('A1')->setValue("hello\nworld"); ``` @@ -618,7 +261,7 @@ You can set a cell's datatype explicitly by using the cell's setValueExplicit method, or the setCellValueExplicit method of a worksheet. Here's an example: -```php +``` php $spreadsheet->getActiveSheet()->getCell('A1') ->setValueExplicit( '25', @@ -630,36 +273,18 @@ $spreadsheet->getActiveSheet()->getCell('A1') You can make a cell a clickable URL by setting its hyperlink property: -```php -$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.example.com'); -$spreadsheet->getActiveSheet()->getCell('E26') - ->getHyperlink() - ->setUrl('https://www.example.com'); +``` php +$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net'); +$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl('https://www.example.com'); ``` If you want to make a hyperlink to another worksheet/cell, use the following code: -```php -$spreadsheet->getActiveSheet() - ->setCellValue('E27', 'go to another sheet'); -$spreadsheet->getActiveSheet()->getCell('E27') - ->getHyperlink() - ->setUrl("sheet://'Sheetname'!A1"); -``` - -Excel automatically supplies a special style when a hyperlink is -entered into a cell. PhpSpreadsheet cannot do so. However, -starting with release 4.3, -you can mimic Excel's behavior with: -```php -$spreadsheet->getActiveSheet() - ->getStyle('E26') - ->getFont() - ->setHyperlinkTheme(); +``` php +$spreadsheet->getActiveSheet()->setCellValue('E26', 'www.phpexcel.net'); +$spreadsheet->getActiveSheet()->getCell('E26')->getHyperlink()->setUrl("sheet://'Sheetname'!A1"); ``` -This will set underline (all formats) and text color (always -for Xlsx, and usually for other formats). ## Setting Printer Options for Excel files @@ -668,7 +293,7 @@ for Xlsx, and usually for other formats). Setting a worksheet's page orientation and size can be done using the following lines of code: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup() ->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE); $spreadsheet->getActiveSheet()->getPageSetup() @@ -676,22 +301,7 @@ $spreadsheet->getActiveSheet()->getPageSetup() ``` Note that there are additional page settings available. Please refer to -the [API documentation](https://phpoffice.github.io/PhpSpreadsheet) for all possible options. - -The default papersize is initially PAPERSIZE_LETTER. However, this default -can be changed for new sheets with the following call: -```php -\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::setPaperSizeDefault( - \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::PAPERSIZE_A4 -); -``` - -The default orientation is ORIENTATION_DEFAULT, which will be treated as Portrait in Excel. However, this default can be changed for new sheets with the following call: -```php -\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::setOrientationDefault( - \PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE -); -``` +the [API documentation](https://phpoffice.github.io/PhpSpreadsheet/master) for all possible options. ### Page Setup: Scaling options @@ -714,7 +324,7 @@ setFitToHeight(...) | 1 | setFitToPage(TRUE) | value 0 mean Here is how to fit to 1 page wide by infinite pages tall: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup()->setFitToWidth(1); $spreadsheet->getActiveSheet()->getPageSetup()->setFitToHeight(0); ``` @@ -730,7 +340,7 @@ the initial values. To set page margins for a worksheet, use this code: -```php +``` php $spreadsheet->getActiveSheet()->getPageMargins()->setTop(1); $spreadsheet->getActiveSheet()->getPageMargins()->setRight(0.75); $spreadsheet->getActiveSheet()->getPageMargins()->setLeft(0.75); @@ -746,7 +356,7 @@ Note that the margin values are specified in inches. To center a page horizontally/vertically, you can use the following code: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup()->setHorizontalCentered(true); $spreadsheet->getActiveSheet()->getPageSetup()->setVerticalCentered(false); ``` @@ -756,7 +366,7 @@ $spreadsheet->getActiveSheet()->getPageSetup()->setVerticalCentered(false); Setting a worksheet's print header and footer can be done using the following lines of code: -```php +``` php $spreadsheet->getActiveSheet()->getHeaderFooter() ->setOddHeader('&C&HPlease treat this document as confidential!'); $spreadsheet->getActiveSheet()->getHeaderFooter() @@ -842,9 +452,7 @@ $drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing(); $drawing->setName('PhpSpreadsheet logo'); $drawing->setPath('./images/PhpSpreadsheet_logo.png'); $drawing->setHeight(36); -$spreadsheet->getActiveSheet() - ->getHeaderFooter() - ->addImage($drawing, \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooter::IMAGE_HEADER_LEFT); +$spreadsheet->getActiveSheet()->getHeaderFooter()->addImage($drawing, \PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooter::IMAGE_HEADER_LEFT); ``` ### Setting printing breaks on a row or column @@ -852,13 +460,13 @@ $spreadsheet->getActiveSheet() To set a print break, use the following code, which sets a row break on row 10. -```php +``` php $spreadsheet->getActiveSheet()->setBreak('A10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_ROW); ``` The following line of code sets a print break on column D: -```php +``` php $spreadsheet->getActiveSheet()->setBreak('D10', \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_COLUMN); ``` @@ -867,7 +475,7 @@ $spreadsheet->getActiveSheet()->setBreak('D10', \PhpOffice\PhpSpreadsheet\Worksh To show/hide gridlines when printing, use the following code: ```php -$spreadsheet->getActiveSheet()->setPrintGridlines(true); +$spreadsheet->getActiveSheet()->setShowGridlines(true); ``` ### Setting rows/columns to repeat at top/left @@ -876,7 +484,7 @@ PhpSpreadsheet can repeat specific rows/cells at top/left of a page. The following code is an example of how to repeat row 1 to 5 on each printed page of a specific worksheet: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEnd(1, 5); ``` @@ -884,13 +492,13 @@ $spreadsheet->getActiveSheet()->getPageSetup()->setRowsToRepeatAtTopByStartAndEn To specify a worksheet's printing area, use the following code: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5'); ``` There can also be multiple printing areas in a single worksheet: -```php +``` php $spreadsheet->getActiveSheet()->getPageSetup()->setPrintArea('A1:E5,G4:M20'); ``` @@ -903,7 +511,7 @@ For example, one can set the foreground colour of a cell to red, aligned to the right, and the border to black and thick border style. Let's do that on cell B2: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('B2') ->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED); $spreadsheet->getActiveSheet()->getStyle('B2') @@ -925,7 +533,7 @@ $spreadsheet->getActiveSheet()->getStyle('B2') `getStyle()` also accepts a cell range as a parameter. For example, you can set a red background color on a range of cells: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('B3:B7')->getFill() ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID) ->getStartColor()->setARGB('FFFF0000'); @@ -936,14 +544,11 @@ getStyle('A1:M500'), rather than styling the cells individually in a loop. This is much faster compared to looping through cells and styling them individually. -**Tip** If you are styling entire row(s) or column(s), e.g. getStyle('A:A'), it is recommended to use applyFromArray as described below rather than setting the styles individually as described above. -Also, starting with release 3.9.0, you should use getRowStyle or getColumnStyle to get the style for an entire row or column. - There is also an alternative manner to set styles. The following code sets a cell's style to font bold, alignment right, top border thin and a gradient fill: -```php +``` php $styleArray = [ 'font' => [ 'bold' => true, @@ -973,7 +578,7 @@ $spreadsheet->getActiveSheet()->getStyle('A3')->applyFromArray($styleArray); Or with a range of cells: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('B3:B7')->applyFromArray($styleArray); ``` @@ -982,13 +587,6 @@ execution whenever you are setting more than one style property. But the difference may barely be measurable unless you have many different styles in your workbook. -You can perform the opposite function, exporting a Style as an array, -as follows: - -``` php -$styleArray = $spreadsheet->getActiveSheet()->getStyle('A3')->exportArray(); -``` - ### Number formats You often want to format numbers in Excel. For example you may want a @@ -1004,7 +602,7 @@ number format code unless you need a custom number format. In PhpSpreadsheet, you can also apply various predefined number formats. Example: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat() ->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1); ``` @@ -1016,7 +614,7 @@ up as 1.587,20) You can achieve exactly the same as the above by using this: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat() ->setFormatCode('#,##0.00'); ``` @@ -1025,7 +623,7 @@ In Microsoft Office Excel, as well as in PhpSpreadsheet, you will have to interact with raw number format codes whenever you need some special custom number format. Example: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat() ->setFormatCode('[Blue][>=3000]$#,##0;[Red][<0]$#,##0;$#,##0'); ``` @@ -1033,7 +631,7 @@ $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat() Another example is when you want numbers zero-padded with leading zeros to a fixed length: -```php +``` php $spreadsheet->getActiveSheet()->getCell('A1')->setValue(19); $spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat() ->setFormatCode('0000'); // will show as 0019 in Excel @@ -1048,7 +646,7 @@ The readers shipped with PhpSpreadsheet come to the rescue. Load your template workbook using e.g. Xlsx reader to reveal the number format code. Example how read a number format code for cell A1: -```php +``` php $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx'); $spreadsheet = $reader->load('template.xlsx'); var_dump($spreadsheet->getActiveSheet()->getStyle('A1')->getNumberFormat()->getFormatCode()); @@ -1063,14 +661,14 @@ code in *xl/styles.xml*. Let's set vertical alignment to the top for cells A1:D4 -```php +``` php $spreadsheet->getActiveSheet()->getStyle('A1:D4') ->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_TOP); ``` Here is how to achieve wrap text: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('A1:D4') ->getAlignment()->setWrapText(true); ``` @@ -1080,47 +678,18 @@ $spreadsheet->getActiveSheet()->getStyle('A1:D4') It is possible to set the default style of a workbook. Let's set the default font to Arial size 8: -```php +``` php $spreadsheet->getDefaultStyle()->getFont()->setName('Arial'); $spreadsheet->getDefaultStyle()->getFont()->setSize(8); ``` -Excel also offers "theme fonts", with separate font names for major (header) and minor (body) text. PhpSpreadsheet will use the Excel 2007 default (Cambria) for major (default is Calibri Light in Excel 2013+); PhpSpreadsheet default for minor is Calibri, which is used by Excel 2007+. To align the default font name with the minor font name: - -```php -$spreadsheet->getTheme() - ->setThemeFontName('custom') - ->setMinorFontValues('Arial', 'Arial', 'Arial', []); -$spreadsheet->getDefaultStyle()->getFont()->setScheme('minor'); -``` - -All cells bound to the theme fonts (via the `Font::setScheme` method) can be easily changed to a different font in Excel. To do this in PhpSpreadsheet, an additional method call is needed: -```php -$spreadsheet->resetThemeFonts(); -``` - -### Charset for Arabic and Persian Fonts - -It is unknown why this should be needed. However, some Excel -users have reported better results if the internal declaration for an -Arabic/Persian font includes a `charset` declaration. -This seems like a bug in Excel, but, starting with release 4.4, -this can be accomplished at the spreadsheet level, via: -```php -$spreadsheet->addFontCharset('C Nazanin'); -``` -As many charsets as desired can be added in this manner. -There is a second optional parameter specifying the charset id -to this method, but, since this seems to be needed only for -Arabic/Persian, that is its default value. - ### Styling cell borders In PhpSpreadsheet it is easy to apply various borders on a rectangular selection. Here is how to apply a thick red border outline around cells B2:G8. -```php +``` php $styleArray = [ 'borders' => [ 'outline' => [ @@ -1171,26 +740,6 @@ vertical/horizontal, left/right/top/bottom/diagonal. This border hierarchy can be utilized to achieve various effects in an easy manner. -#### Advanced borders - -There is a second parameter `$advancedBorders` which can be supplied to applyFromArray. The default is `true`; when set to this value, the border styles are applied to the range as a whole, not to the individual cells. When set to `false`, the border styles are applied to each cell. The following code and screenshot demonstrates the difference. - -```php -$sheet->setShowGridlines(false); -$styleArray = [ - 'borders' => [ - 'bottom' => ['borderStyle' => 'hair', 'color' => ['argb' => 'FFFF0000']], - 'top' => ['borderStyle' => 'hair', 'color' => ['argb' => 'FFFF0000']], - 'right' => ['borderStyle' => 'hair', 'color' => ['argb' => 'FF00FF00']], - 'left' => ['borderStyle' => 'hair', 'color' => ['argb' => 'FF00FF00']], - ], -]; -$sheet->getStyle('B2:C3')->applyFromArray($styleArray); -$sheet->getStyle('B5:C6')->applyFromArray($styleArray, false); -``` - -![08-advance-borders.png](./images/08-advanced-borders.png) - ### Valid array keys for style `applyFromArray()` The following table lists the valid array keys for @@ -1204,75 +753,69 @@ another style array. Array key | Maps to property -------------|------------------- -alignment | setAlignment() -borders | setBorders() -fill | setFill() -font | setFont() -numberFormat | setNumberFormat() -protection | setProtection() -quotePrefix | setQuotePrefix() +fill | getFill() +font | getFont() +borders | getBorders() +alignment | getAlignment() +numberFormat | getNumberFormat() +protection | getProtection() -**\PhpOffice\PhpSpreadsheet\Style\Alignment** +**\PhpOffice\PhpSpreadsheet\Style\Fill** -Array key | Maps to property -----------------|------------------- -horizontal | setHorizontal() -justifyLastLine | setJustifyLastLine() -indent | setIndent() -readOrder | setReadOrder() -shrinkToFit | setShrinkToFit() -textRotation | setTextRotation() -vertical | setVertical() -wrapText | setWrapText() +Array key | Maps to property +-----------|------------------- +fillType | setFillType() +rotation | setRotation() +startColor | getStartColor() +endColor | getEndColor() +color | getStartColor() -**\PhpOffice\PhpSpreadsheet\Style\Border** +**\PhpOffice\PhpSpreadsheet\Style\Font** Array key | Maps to property ------------|------------------- -borderStyle | setBorderStyle() -color | setColor() - -**\PhpOffice\PhpSpreadsheet\Style\Borders** - -Array key | Maps to property -------------------|------------------- +name | setName() +bold | setBold() +italic | setItalic() +underline | setUnderline() +strikethrough | setStrikethrough() +color | getColor() +size | setSize() +superscript | setSuperscript() +subscript | setSubscript() + +**\PhpOffice\PhpSpreadsheet\Style\Borders** + +Array key | Maps to property +------------------|------------------- allBorders | getLeft(); getRight(); getTop(); getBottom() -bottom | getBottom() -diagonal | getDiagonal() -diagonalDirection | setDiagonalDirection() left | getLeft() right | getRight() top | getTop() +bottom | getBottom() +diagonal | getDiagonal() +vertical | getVertical() +horizontal | getHorizontal() +diagonalDirection | setDiagonalDirection() +outline | setOutline() -**\PhpOffice\PhpSpreadsheet\Style\Color** +**\PhpOffice\PhpSpreadsheet\Style\Border** Array key | Maps to property ------------|------------------- -argb | setARGB() - -**\PhpOffice\PhpSpreadsheet\Style\Fill** - -Array key | Maps to property ------------|------------------- -color | getStartColor() -endColor | getEndColor() -fillType | setFillType() -rotation | setRotation() -startColor | getStartColor() +borderStyle | setBorderStyle() +color | getColor() -**\PhpOffice\PhpSpreadsheet\Style\Font** +**\PhpOffice\PhpSpreadsheet\Style\Alignment** Array key | Maps to property ------------|------------------- -bold | setBold() -color | getColor() -italic | setItalic() -name | setName() -size | setSize() -strikethrough | setStrikethrough() -subscript | setSubscript() -superscript | setSuperscript() -underline | setUnderline() +horizontal | setHorizontal() +vertical | setVertical() +textRotation| setTextRotation() +wrapText | setWrapText() +shrinkToFit | setShrinkToFit() +indent | setIndent() **\PhpOffice\PhpSpreadsheet\Style\NumberFormat** @@ -1296,7 +839,7 @@ is below zero, and to green if its value is zero or more. One can set a conditional style ruleset to a cell using the following code: -```php +``` php $conditional1 = new \PhpOffice\PhpSpreadsheet\Style\Conditional(); $conditional1->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_CELLIS); $conditional1->setOperatorType(\PhpOffice\PhpSpreadsheet\Style\Conditional::OPERATOR_LESSTHAN); @@ -1321,60 +864,20 @@ $spreadsheet->getActiveSheet()->getStyle('B2')->setConditionalStyles($conditiona If you want to copy the ruleset to other cells, you can duplicate the style object: -```php +``` php $spreadsheet->getActiveSheet() - ->duplicateConditionalStyle( - $spreadsheet->getActiveSheet()->getConditionalStyles('B2'), + ->duplicateStyle( + $spreadsheet->getActiveSheet()->getStyle('B2'), 'B3:B7' ); ``` -More detailed documentation of the Conditional Formatting options and rules, and the use of Wizards to help create them, can be found in [a dedicated section of the documentation](https://phpspreadsheet.readthedocs.io/en/latest/topics/conditional-formatting/). - -### DataBar of Conditional formatting -The basics are the same as conditional formatting. -Additional DataBar object to conditional formatting. - -For example, the following code will result in the conditional formatting shown in the image. -```php -$conditional = new Conditional(); -$conditional->setConditionType(Conditional::CONDITION_DATABAR); -$conditional->setDataBar(new ConditionalDataBar()); -$conditional->getDataBar() - ->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2')) - ->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max')) - ->setColor('FFFF555A'); -$ext = $conditional - ->getDataBar() - ->setConditionalFormattingRuleExt(new ConditionalFormattingRuleExtension()) - ->getConditionalFormattingRuleExt(); - -$ext->setCfRule('dataBar'); -$ext->setSqref('A1:A5'); // target CellCoordinates -$ext->setDataBarExt(new ConditionalDataBarExtension()); -$ext->getDataBarExt() - ->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('num', '2')) - ->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('autoMax')) - ->setMinLength(0) - ->setMaxLength(100) - ->setBorder(true) - ->setDirection('rightToLeft') - ->setNegativeBarBorderColorSameAsPositive(false) - ->setBorderColor('FFFF555A') - ->setNegativeFillColor('FFFF0000') - ->setNegativeBorderColor('FFFF0000') - ->setAxisColor('FF000000'); - -``` - -![10-databar-of-conditional-formatting.png](./images/10-databar-of-conditional-formatting.png) - ## Add a comment to a cell To add a comment to a cell, use the following code. The example below adds a comment to cell E11: -```php +``` php $spreadsheet->getActiveSheet() ->getComment('E11') ->setAuthor('Mark Baker'); @@ -1389,36 +892,19 @@ $spreadsheet->getActiveSheet() ->getComment('E11') ->getText()->createTextRun('Total amount on the current invoice, excluding VAT.'); ``` -![08-cell-comment.png](./images/08-cell-comment.png) - -## Add a comment with background image to a cell -To add a comment with background image to a cell, use the following code: - -```php -$sheet = $spreadsheet->getActiveSheet(); -$sheet->setCellValue('B5', 'Gibli Chromo'); -// Add png image to comment background -$drawing = new Drawing(); -$drawing->setName('Gibli Chromo'); -$drawing->setPath('/tmp/gibli_chromo.png'); -$comment = $sheet->getComment('B5'); -$comment->setBackgroundImage($drawing); -// Set the size of the comment equal to the size of the image -$comment->setSizeAsBackgroundImage(); -``` -![08-cell-comment-with-image.png](./images/08-cell-comment-with-image.png) +![08-cell-comment.png](./images/08-cell-comment.png) ## Apply autofilter to a range of cells To apply an autofilter to a range of cells, use the following code: -```php +``` php $spreadsheet->getActiveSheet()->setAutoFilter('A1:C9'); ``` **Make sure that you always include the complete filter range!** Excel -does support setting only the caption row, but that's **not** a best +does support setting only the captionrow, but that's **not** a best practice... ## Setting security on a spreadsheet @@ -1433,107 +919,45 @@ disallow inserting rows on a specific sheet, disallow sorting, ... - Cell: offers the option to lock/unlock a cell as well as show/hide the internal formula. -**Make sure you enable worksheet protection if you need any of the -worksheet or cell protection features!** This can be done using the following -code: - -```php -$spreadsheet->getActiveSheet()->getProtection()->setSheet(true); -``` - -> Note that "protection" is not the same as "encryption". -> Protection is about preventing parts of a spreadsheet from being changed, not about preventing the spreadsheet from being looked at.

-PhpSpreadsheet does not support encrypting a spreadsheet; nor can it read encrypted spreadsheets. - -### Document - An example on setting document security: -```php -$security = $spreadsheet->getSecurity(); -$security->setLockWindows(true); -$security->setLockStructure(true); -$security->setWorkbookPassword("PhpSpreadsheet"); -``` - -Note that there are additional methods setLockRevision and setRevisionsPassword -which apply only to change tracking and history for shared workbooks. - -### Worksheet - -An example on setting worksheet security -(user can sort, insert rows, or format cells without unprotecting): - -```php -$protection = $spreadsheet->getActiveSheet()->getProtection(); -$protection->setPassword('PhpSpreadsheet'); -$protection->setSheet(true); -$protection->setSort(false); -$protection->setInsertRows(false); -$protection->setFormatCells(false); -``` - -Note that allowing sort without providing the sheet password -(similarly with autoFilter) requires that you explicitly -enable the cell ranges for which sort is permitted, -with or without a range password: -```php -$sheet->protectCells('A:A'); // column A can be sorted without password -$sheet->protectCells('B:B', 'sortpw'); // column B can be sorted if the range password sortpw is supplied +``` php +$spreadsheet->getSecurity()->setLockWindows(true); +$spreadsheet->getSecurity()->setLockStructure(true); +$spreadsheet->getSecurity()->setWorkbookPassword("PhpSpreadsheet"); ``` -If writing Xlsx files you can specify the algorithm used to hash the password -before calling `setPassword()` like so: +An example on setting worksheet security: -```php -$protection = $spreadsheet->getActiveSheet()->getProtection(); -$protection->setAlgorithm(Protection::ALGORITHM_SHA_512); -$protection->setSpinCount(20000); -$protection->setPassword('PhpSpreadsheet'); +``` php +$spreadsheet->getActiveSheet() + ->getProtection()->setPassword('PhpSpreadsheet'); +$spreadsheet->getActiveSheet() + ->getProtection()->setSheet(true); +$spreadsheet->getActiveSheet() + ->getProtection()->setSort(true); +$spreadsheet->getActiveSheet() + ->getProtection()->setInsertRows(true); +$spreadsheet->getActiveSheet() + ->getProtection()->setFormatCells(true); ``` -The salt should **not** be set manually and will be automatically generated -when setting a new password. - -### Cell - -An example on setting cell security. -Note that cell security is honored only when sheet is protected. -Also note that the `hidden` property applies only to formulas, -and tells whether the formula is hidden on the formula bar, -not in the cell. +An example on setting cell security: -```php +``` php $spreadsheet->getActiveSheet()->getStyle('B1') ->getProtection() - ->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED) - ->setHidden(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_PROTECTED); + ->setLocked(\PhpOffice\PhpSpreadsheet\Style\Protection::PROTECTION_UNPROTECTED); ``` -## Reading protected spreadsheet - -Spreadsheets that are protected as described above can always be read by -PhpSpreadsheet. There is no need to know the password or do anything special in -order to read a protected file. - -However if you need to implement a password verification mechanism, you can use the -following helper method: - - -```php -$protection = $spreadsheet->getActiveSheet()->getProtection(); -$allowed = $protection->verify('my password'); +**Make sure you enable worksheet protection if you need any of the +worksheet protection features!** This can be done using the following +code: -if ($allowed) { - doSomething(); -} else { - throw new Exception('Incorrect password'); -} +``` php +$spreadsheet->getActiveSheet()->getProtection()->setSheet(true); ``` -If you need to completely prevent reading a file by any tool, including PhpSpreadsheet, -then you are looking for "encryption", not "protection". - ## Setting data validation on a cell Data validation is a powerful feature of Xlsx. It allows to specify an @@ -1544,7 +968,7 @@ filter can be a range (i.e. value must be between 0 and 10), a list The following piece of code only allows numbers between 10 and 20 to be entered in cell B3: -```php +``` php $validation = $spreadsheet->getActiveSheet()->getCell('B3') ->getDataValidation(); $validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_WHOLE ); @@ -1561,9 +985,9 @@ $validation->setFormula2(20); ``` The following piece of code only allows an item picked from a list of -data to be entered in cell B5: +data to be entered in cell B3: -```php +``` php $validation = $spreadsheet->getActiveSheet()->getCell('B5') ->getDataValidation(); $validation->setType( \PhpOffice\PhpSpreadsheet\Cell\DataValidation::TYPE_LIST ); @@ -1587,75 +1011,29 @@ formula is allowed to be maximum 255 characters (not bytes). This sets a limit on how many items you can have in the string "Item A,Item B,Item C". Therefore it is normally a better idea to type the item values directly in some cell range, say A1:A3, and instead use, say, -`$validation->setFormula1('\'Sheet title\'!$A$1:$A$3')`. Another benefit is that +`$validation->setFormula1('Sheet!$A$1:$A$3')`. Another benefit is that the item values themselves can contain the comma `,` character itself. -### Setting Validation on Multiple Cells - Release 3 and Below - If you need data validation on multiple cells, one can clone the ruleset: -```php +``` php $spreadsheet->getActiveSheet()->getCell('B8')->setDataValidation(clone $validation); ``` -Alternatively, one can apply the validation to a range of cells: -```php -$validation->setSqref('B5:B1048576'); -``` - -### Setting Validation on Multiple Cells - Release 4 and Above - -Starting with Release 4, Data Validation can be set simultaneously on several cells/cell ranges. - -```php -$spreadsheet->getActiveSheet()->getDataValidation('A1:A4 D5 E6:E7') - ->set...(...); -``` - -In theory, this means that more than one Data Validation can apply to a cell. -It appears that, when Excel reads a spreadsheet with more than one Data Validation applying to a cell, -whichever appears first in the Xml is what Xml uses. -PhpSpreadsheet will instead apply a DatValidation applying to a single cell first; -then, if it doesn't find such a match, it will use the first applicable definition which is read (or created after or in lieu of reading). -This allows you, for example, to set Data Validation on all but a few cells in a column: -```php -$dv = new DataValidation(); -$dv->setType(DataValidation::TYPE_NONE); -$sheet->setDataValidation('A5:A7', $dv); -$dv = new DataValidation(); -$dv->set...(...); -$sheet->setDataValidation('A:A', $dv); -$dv = new DataValidation(); -$dv->setType(DataValidation::TYPE_NONE); -$sheet->setDataValidation('A9', $dv); -``` - ## Setting a column's width A column's width can be set using the following code: -```php +``` php $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(12); ``` -If you want to set a column width using a different UoM (Unit of Measure), -then you can do so by telling PhpSpreadsheet what UoM the width value -that you are setting is measured in. -Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches), -`cm` (centimeters) and `mm` (millimeters). - -Setting the column width to `-1` tells MS Excel to display the column using its default width. - -```php -$spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(120, 'pt'); -``` - If you want PhpSpreadsheet to perform an automatic width calculation, -use the following code. PhpSpreadsheet will approximate the column width -to the width of the widest value displayed in that column. +use the following code. PhpSpreadsheet will approximate the column with +to the width of the widest column value. -```php +``` php $spreadsheet->getActiveSheet()->getColumnDimension('B')->setAutoSize(true); ``` @@ -1692,7 +1070,7 @@ To set a worksheet's column visibility, you can use the following code. The first line explicitly shows the column C, the second line hides column D. -```php +``` php $spreadsheet->getActiveSheet()->getColumnDimension('C')->setVisible(true); $spreadsheet->getActiveSheet()->getColumnDimension('D')->setVisible(false); ``` @@ -1701,7 +1079,7 @@ $spreadsheet->getActiveSheet()->getColumnDimension('D')->setVisible(false); To group/outline a column, you can use the following code: -```php +``` php $spreadsheet->getActiveSheet()->getColumnDimension('E')->setOutlineLevel(1); ``` @@ -1709,7 +1087,7 @@ You can also collapse the column. Note that you should also set the column invisible, otherwise the collapse will not be visible in Excel 2007. -```php +``` php $spreadsheet->getActiveSheet()->getColumnDimension('E')->setCollapsed(true); $spreadsheet->getActiveSheet()->getColumnDimension('E')->setVisible(false); ``` @@ -1720,7 +1098,7 @@ on collapsing. You can instruct PhpSpreadsheet to add a summary to the right (default), or to the left. The following code adds the summary to the left: -```php +``` php $spreadsheet->getActiveSheet()->setShowSummaryRight(false); ``` @@ -1728,7 +1106,7 @@ $spreadsheet->getActiveSheet()->setShowSummaryRight(false); A row's height can be set using the following code: -```php +``` php $spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100); ``` @@ -1736,34 +1114,12 @@ Excel measures row height in points, where 1 pt is 1/72 of an inch (or about 0.35mm). The default value is 12.75 pts; and the permitted range of values is between 0 and 409 pts, where 0 pts is a hidden row. -If you want to set a row height using a different UoM (Unit of Measure), -then you can do so by telling PhpSpreadsheet what UoM the height value -that you are setting is measured in. -Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches), -`cm` (centimeters) and `mm` (millimeters). - -```php -$spreadsheet->getActiveSheet()->getRowDimension('10')->setRowHeight(100, 'pt'); -``` - -Setting the row height to `-1` tells MS Excel to display the column using its default height, which is based on the character font size. - -If you have wrapped text in a cell, then the `-1` default will only set the row height to display a single line of that wrapped text. -If you need to calculate the actual height for the row, then count the lines that should be displayed (count the `\n` and add 1); then adjust for the font. -The adjustment for Calibri 11 is approximately 14.5; for Calibri 12 15.9, etc. -```php -$spreadsheet->getActiveSheet()->getRowDimension(1)->setRowHeight( - 14.5 * (substr_count($sheet->getCell('A1')->getValue(), "\n") + 1) -); -``` - - ## Show/hide a row To set a worksheet''s row visibility, you can use the following code. The following example hides row number 10. -```php +``` php $spreadsheet->getActiveSheet()->getRowDimension('10')->setVisible(false); ``` @@ -1775,21 +1131,21 @@ AutoFilter range if you save the file. To group/outline a row, you can use the following code: -```php +``` php $spreadsheet->getActiveSheet()->getRowDimension('5')->setOutlineLevel(1); ``` You can also collapse the row. Note that you should also set the row invisible, otherwise the collapse will not be visible in Excel 2007. -```php +``` php $spreadsheet->getActiveSheet()->getRowDimension('5')->setCollapsed(true); $spreadsheet->getActiveSheet()->getRowDimension('5')->setVisible(false); ``` Here's an example which collapses rows 50 to 80: -```php +``` php for ($i = 51; $i <= 80; $i++) { $spreadsheet->getActiveSheet()->setCellValue('A' . $i, "FName $i"); $spreadsheet->getActiveSheet()->setCellValue('B' . $i, "LName $i"); @@ -1806,101 +1162,34 @@ $spreadsheet->getActiveSheet()->getRowDimension(81)->setCollapsed(true); You can instruct PhpSpreadsheet to add a summary below the collapsible rows (default), or above. The following code adds the summary above: -```php +``` php $spreadsheet->getActiveSheet()->setShowSummaryBelow(false); ``` -## Merge/Unmerge cells +## Merge/unmerge cells -If you have a big piece of data you want to display in a worksheet, or a -heading that needs to span multiple sub-heading columns, you can merge -two or more cells together, to become one cell. This can be done using -the following code: +If you have a big piece of data you want to display in a worksheet, you +can merge two or more cells together, to become one cell. This can be +done using the following code: -```php +``` php $spreadsheet->getActiveSheet()->mergeCells('A18:E22'); ``` -Removing a merge can be done using the `unmergeCells()` method: +Removing a merge can be done using the unmergeCells method: -```php +``` php $spreadsheet->getActiveSheet()->unmergeCells('A18:E22'); ``` -MS Excel itself doesn't yet offer the functionality to simply hide the merged cells, or to merge the content of cells into a single cell, but it is available in Open/Libre Office. - -### Merge with MERGE_CELL_CONTENT_EMPTY - -The default behaviour is to empty all cells except for the top-left corner cell in the merge range; and this is also the default behaviour for the `mergeCells()` method in PhpSpreadsheet. -When this behaviour is applied, those cell values will be set to null; and if they are subsequently Unmerged, they will be empty cells. - -Passing an extra flag value to the `mergeCells()` method in PhpSpreadsheet can change this behaviour. - -![12-01-MergeCells-Options.png](./images/12-01-MergeCells-Options.png) - -Possible flag values are: -- Worksheet::MERGE_CELL_CONTENT_EMPTY (the default) -- Worksheet::MERGE_CELL_CONTENT_HIDE -- Worksheet::MERGE_CELL_CONTENT_MERGE - -### Merge with MERGE_CELL_CONTENT_HIDE - -The first alternative, available only in OpenOffice, is to hide those cells, but to leave their content intact. -When a file saved as `Xlsx` in those applications is opened in MS Excel, and those cells are unmerged, the original content will still be present. - -```php -$spreadsheet->getActiveSheet()->mergeCells('A1:C3', Worksheet::MERGE_CELL_CONTENT_HIDE); -``` - -Will replicate that behaviour. - -### Merge with MERGE_CELL_CONTENT_MERGE - -The second alternative, available in both OpenOffice and LibreOffice is to merge the content of every cell in the merge range into the top-left cell, while setting those hidden cells to empty. - -```php -$spreadsheet->getActiveSheet()->mergeCells('A1:C3', Worksheet::MERGE_CELL_CONTENT_MERGE); -``` - -Particularly when the merged cells contain formulas, the logic for this merge seems strange: -walking through the merge range, each cell is calculated in turn, and appended to the "master" cell, then it is emptied, so any subsequent calculations that reference the cell see an empty cell, not the pre-merge value. -For example, suppose our spreadsheet contains - -![12-01-MergeCells-Options-2.png](./images/12-01-MergeCells-Options-2.png) - -where `B2` is the formula `=5-B1` and `C2` is the formula `=A2/B2`, -and we want to merge cells `A2` to `C2` with all the cell values merged. -The result is: - -![12-01-MergeCells-Options-3.png](./images/12-01-MergeCells-Options-3.png) - -The cell value `12` from cell `A2` is fixed; the value from `B2` is the result of the formula `=5-B1` (`4`, which is appended to our merged value), and cell `B2` is then emptied, so when we evaluate cell `C2` with the formula `=A2/B2` it gives us `12 / 0` which results in a `#DIV/0!` error (so the error `#DIV/0!` is appended to our merged value rather than the original calculation result of `3`). - -## Inserting or Removing rows/columns +## Inserting rows/columns You can insert/remove rows/columns at a specific position. The following code inserts 2 new rows, right before row 7: -```php +``` php $spreadsheet->getActiveSheet()->insertNewRowBefore(7, 2); ``` -while -```php -$spreadsheet->getActiveSheet()->removeRow(7, 2); -``` -will remove 2 rows starting at row number 7 (ie. rows 7 and 8). - -Equivalent methods exist for inserting/removing columns: - -```php -$spreadsheet->getActiveSheet()->removeColumn('C', 2); -``` - -All subsequent rows (or columns) will be moved to allow the insertion (or removal) with all formulas referencing thise cells adjusted accordingly. - -Note that this is a fairly intensive process, particularly with large worksheets, and especially if you are inserting/removing rows/columns from near beginning of the worksheet. - -If you need to insert/remove several consecutive rows/columns, always use the second argument rather than making multiple calls to insert/remove a single row/column if possible. ## Add a drawing to a worksheet @@ -1909,7 +1198,7 @@ to a worksheet. Therefore, you must first instantiate a new `\PhpOffice\PhpSpreadsheet\Worksheet\Drawing`, and assign its properties a meaningful value: -```php +``` php $drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); $drawing->setName('Logo'); $drawing->setDescription('Logo'); @@ -1921,13 +1210,13 @@ To add the above drawing to the worksheet, use the following snippet of code. PhpSpreadsheet creates the link between the drawing and the worksheet: -```php +``` php $drawing->setWorksheet($spreadsheet->getActiveSheet()); ``` You can set numerous properties on a drawing, here are some examples: -```php +``` php $drawing->setName('Paid'); $drawing->setDescription('Paid'); $drawing->setPath('./images/paid.png'); @@ -1941,7 +1230,7 @@ $drawing->getShadow()->setDirection(45); You can also add images created using GD functions without needing to save them to disk first as In-Memory drawings. -```php +``` php // Use GD to create an in-memory image $gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream'); $textColor = imagecolorallocate($gdImage, 255, 255, 255); @@ -1961,22 +1250,6 @@ $drawing->setHeight(36); $drawing->setWorksheet($spreadsheet->getActiveSheet()); ``` -Note that GD images are memory-intensive. - -### Creating a Drawing from string or stream data - -If you want to create a drawing from a string containing the binary image data, or from an external datasource such as an S3 bucket, then you can create a new MemoryDrawing from these sources using the `fromString()` or `fromStream()` static methods. - -```php -$drawing = MemoryDrawing::fromString($imageString); -``` - -```php -$drawing = MemoryDrawing::fromStream($imageStreamFromS3Bucket); -``` - -Note that this is a memory-intensive process, like all gd images; and also creates a temporary file. - ## Reading Images from a worksheet A commonly asked question is how to retrieve the images from a workbook @@ -1985,12 +1258,10 @@ that has been loaded, and save them as individual image files to disk. The following code extracts images from the current active worksheet, and writes each as a separate file. -```php -use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing; +``` php $i = 0; - foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) { - if ($drawing instanceof MemoryDrawing) { + if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing) { ob_start(); call_user_func( $drawing->getRenderingFunction(), @@ -1999,39 +1270,24 @@ foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $drawing) { $imageContents = ob_get_contents(); ob_end_clean(); switch ($drawing->getMimeType()) { - case MemoryDrawing::MIMETYPE_PNG : + case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_PNG : $extension = 'png'; break; - case MemoryDrawing::MIMETYPE_GIF: + case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_GIF: $extension = 'gif'; break; - case MemoryDrawing::MIMETYPE_JPEG : + case \PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing::MIMETYPE_JPEG : $extension = 'jpg'; break; } } else { - if ($drawing->getPath()) { - // Check if the source is a URL or a file path - if ($drawing->getIsURL()) { - $imageContents = file_get_contents($drawing->getPath()); - $filePath = tempnam(sys_get_temp_dir(), 'Drawing'); - file_put_contents($filePath , $imageContents); - $mimeType = mime_content_type($filePath); - // You could use the below to find the extension from mime type. - // https://gist.github.com/alexcorvi/df8faecb59e86bee93411f6a7967df2c#gistcomment-2722664 - $extension = File::mime2ext($mimeType); - unlink($filePath); - } - else { - $zipReader = fopen($drawing->getPath(),'r'); - $imageContents = ''; - while (!feof($zipReader)) { - $imageContents .= fread($zipReader,1024); - } - fclose($zipReader); - $extension = $drawing->getExtension(); - } + $zipReader = fopen($drawing->getPath(),'r'); + $imageContents = ''; + while (!feof($zipReader)) { + $imageContents .= fread($zipReader,1024); } + fclose($zipReader); + $extension = $drawing->getExtension(); } $myFileName = '00_Image_'.++$i.'.'.$extension; file_put_contents($myFileName,$imageContents); @@ -2044,20 +1300,16 @@ Adding rich text to a cell can be done using `\PhpOffice\PhpSpreadsheet\RichText\RichText` instances. Here''s an example, which creates the following rich text string: -> This invoice is ***payable within thirty days after the end of the -> month*** unless specified otherwise on the invoice. +> This invoice is ***payable within thirty days after the end of the +> month*** unless specified otherwise on the invoice. -```php +``` php $richText = new \PhpOffice\PhpSpreadsheet\RichText\RichText(); $richText->createText('This invoice is '); $payable = $richText->createTextRun('payable within thirty days after the end of the month'); $payable->getFont()->setBold(true); $payable->getFont()->setItalic(true); -$payable->getFont()->setColor( - new \PhpOffice\PhpSpreadsheet\Style\Color( - \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN - ) -); +$payable->getFont()->setColor( new \PhpOffice\PhpSpreadsheet\Style\Color( \PhpOffice\PhpSpreadsheet\Style\Color::COLOR_DARKGREEN ) ); $richText->createText(', unless specified otherwise on the invoice.'); $spreadsheet->getActiveSheet()->getCell('A18')->setValue($richText); ``` @@ -2067,7 +1319,7 @@ $spreadsheet->getActiveSheet()->getCell('A18')->setValue($richText); PhpSpreadsheet supports the definition of named ranges. These can be defined using the following code: -```php +``` php // Add some data $spreadsheet->setActiveSheetIndex(0); $spreadsheet->getActiveSheet()->setCellValue('A1', 'Firstname:'); @@ -2076,73 +1328,14 @@ $spreadsheet->getActiveSheet()->setCellValue('B1', 'Maarten'); $spreadsheet->getActiveSheet()->setCellValue('B2', 'Balliauw'); // Define named ranges -$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonFN', $spreadsheet->getActiveSheet(), '$B$1')); -$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonLN', $spreadsheet->getActiveSheet(), '$B$2')); +$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonFN', $spreadsheet->getActiveSheet(), 'B1') ); +$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('PersonLN', $spreadsheet->getActiveSheet(), 'B2') ); ``` Optionally, a fourth parameter can be passed defining the named range local (i.e. only usable on the current worksheet). Named ranges are global by default. -## Define a named formula - -In addition to named ranges, PhpSpreadsheet also supports the definition of named formulas. These can be -defined using the following code: - -```php -// Add some data -$spreadsheet->setActiveSheetIndex(0); -$worksheet = $spreadsheet->getActiveSheet(); -$worksheet - ->setCellValue('A1', 'Product') - ->setCellValue('B1', 'Quantity') - ->setCellValue('C1', 'Unit Price') - ->setCellValue('D1', 'Price') - ->setCellValue('E1', 'VAT') - ->setCellValue('F1', 'Total'); - -// Define named formula -$spreadsheet->addNamedFormula( new \PhpOffice\PhpSpreadsheet\NamedFormula('GERMAN_VAT_RATE', $worksheet, '=16.0%')); -$spreadsheet->addNamedFormula( new \PhpOffice\PhpSpreadsheet\NamedFormula('CALCULATED_PRICE', $worksheet, '=$B1*$C1')); -$spreadsheet->addNamedFormula( new \PhpOffice\PhpSpreadsheet\NamedFormula('GERMAN_VAT', $worksheet, '=$D1*GERMAN_VAT_RATE')); -$spreadsheet->addNamedFormula( new \PhpOffice\PhpSpreadsheet\NamedFormula('TOTAL_INCLUDING_VAT', $worksheet, '=$D1+$E1')); - -$worksheet - ->setCellValue('A2', 'Advanced Web Application Architecture') - ->setCellValue('B2', 2) - ->setCellValue('C2', 23.0) - ->setCellValue('D2', '=CALCULATED_PRICE') - ->setCellValue('E2', '=GERMAN_VAT') - ->setCellValue('F2', '=TOTAL_INCLUDING_VAT'); -$spreadsheet->getActiveSheet() - ->setCellValue('A3', 'Object Design Style Guide') - ->setCellValue('B3', 5) - ->setCellValue('C3', 12.0) - ->setCellValue('D3', '=CALCULATED_PRICE') - ->setCellValue('E3', '=GERMAN_VAT') - ->setCellValue('F3', '=TOTAL_INCLUDING_VAT'); -$spreadsheet->getActiveSheet() - ->setCellValue('A4', 'PHP For the Web') - ->setCellValue('B4', 3) - ->setCellValue('C4', 10.0) - ->setCellValue('D4', '=CALCULATED_PRICE') - ->setCellValue('E4', '=GERMAN_VAT') - ->setCellValue('F4', '=TOTAL_INCLUDING_VAT'); - -// Use a relative named range to provide the totals for rows 2-4 -$spreadsheet->addNamedRange( new \PhpOffice\PhpSpreadsheet\NamedRange('COLUMN_TOTAL', $worksheet, '=A$2:A$4') ); - -$spreadsheet->getActiveSheet() - ->setCellValue('B6', '=SUBTOTAL(109,COLUMN_TOTAL)') - ->setCellValue('D6', '=SUBTOTAL(109,COLUMN_TOTAL)') - ->setCellValue('E6', '=SUBTOTAL(109,COLUMN_TOTAL)') - ->setCellValue('F6', '=SUBTOTAL(109,COLUMN_TOTAL)'); -``` - -As with named ranges, an optional fourth parameter can be passed defining the named formula -scope as local (i.e. only usable on the specified worksheet). Otherwise, named formulas are -global by default. - ## Redirect output to a client's web browser Sometimes, one really wants to output a file to a client''s browser, @@ -2169,7 +1362,7 @@ your document is needed, it is recommended not to use `php://output`. Example of a script redirecting an Excel 2007 file to the client's browser: -```php +``` php /* Here there will be some code where you create $spreadsheet */ // redirect output to client browser @@ -2183,7 +1376,7 @@ $writer->save('php://output'); Example of a script redirecting an Xls file to the client's browser: -```php +``` php /* Here there will be some code where you create $spreadsheet */ // redirect output to client browser @@ -2211,47 +1404,18 @@ at the client browser, and/or that headers cannot be set by PHP Default column width can be set using the following code: -```php +``` php $spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(12); ``` -Excel measures column width in its own proprietary units, based on the number -of characters that will be displayed in the default font. - -If you want to set the default column width using a different UoM (Unit of Measure), -then you can do so by telling PhpSpreadsheet what UoM the width value -that you are setting is measured in. -Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches), -`cm` (centimeters) and `mm` (millimeters). - -```php -$spreadsheet->getActiveSheet()->getDefaultColumnDimension()->setWidth(400, 'pt'); -``` -and PhpSpreadsheet will handle the internal conversion. - ## Setting the default row height Default row height can be set using the following code: -```php +``` php $spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(15); ``` -Excel measures row height in points, where 1 pt is 1/72 of an inch (or -about 0.35mm). The default value is 12.75 pts; and the permitted range -of values is between 0 and 409 pts, where 0 pts is a hidden row. - -If you want to set a row height using a different UoM (Unit of Measure), -then you can do so by telling PhpSpreadsheet what UoM the height value -that you are setting is measured in. -Valid units are `pt` (points), `px` (pixels), `pc` (pica), `in` (inches), -`cm` (centimeters) and `mm` (millimeters). - -```php -$spreadsheet->getActiveSheet()->getDefaultRowDimension()->setRowHeight(100, 'pt'); -``` - - ## Add a GD drawing to a worksheet There might be a situation where you want to generate an in-memory image @@ -2261,7 +1425,7 @@ file to a temporary location. Here''s an example which generates an image in memory and adds it to the active worksheet: -```php +``` php // Generate an image $gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream'); $textColor = imagecolorallocate($gdImage, 255, 255, 255); @@ -2282,7 +1446,7 @@ $drawing->setWorksheet($spreadsheet->getActiveSheet()); To set a worksheet's zoom level, the following code can be used: -```php +``` php $spreadsheet->getActiveSheet()->getSheetView()->setZoomScale(75); ``` @@ -2293,7 +1457,7 @@ Note that zoom level should be in range 10 - 400. Sometimes you want to set a color for sheet tab. For example you can have a red sheet tab: -```php +``` php $worksheet->getTabColor()->setRGB('FF0000'); ``` @@ -2301,7 +1465,7 @@ $worksheet->getTabColor()->setRGB('FF0000'); If you need to create more worksheets in the workbook, here is how: -```php +``` php $worksheet1 = $spreadsheet->createSheet(); $worksheet1->setTitle('Another sheet'); ``` @@ -2314,7 +1478,7 @@ worksheets in the workbook. Set a worksheet to be **hidden** using this code: -```php +``` php $spreadsheet->getActiveSheet() ->setSheetState(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::SHEETSTATE_HIDDEN); ``` @@ -2336,7 +1500,7 @@ Worksheets can be set individually whether column `A` should start at left or right side. Default is left. Here is how to set columns from right-to-left. -```php +``` php // right-to-left worksheet $spreadsheet->getActiveSheet()->setRightToLeft(true); ``` diff --git a/docs/topics/settings.md b/docs/topics/settings.md index ea53dcfb42..a9aae9f923 100644 --- a/docs/topics/settings.md +++ b/docs/topics/settings.md @@ -13,7 +13,7 @@ Read more about [memory saving](./memory_saving.md). To enable cell caching, you must provide your own implementation of cache like so: -```php +``` php $cache = new MyCustomPsr16Implementation(); \PhpOffice\PhpSpreadsheet\Settings::setCache($cache); @@ -25,7 +25,7 @@ Some localisation elements have been included in PhpSpreadsheet. You can set a locale by changing the settings. To set the locale to Brazilian Portuguese you would use: -```php +``` php $locale = 'pt_br'; $validLocale = \PhpOffice\PhpSpreadsheet\Settings::setLocale($locale); if (!$validLocale) { @@ -42,21 +42,4 @@ then the `setLocale()` method will return an error, and American English More details of the features available once a locale has been set, including a list of the languages and locales currently supported, can be found in [Locale Settings for -Formulas](./recipes.md#locale-settings-for-formulas). - -## HTTP client - -In order to use the `WEBSERVICE` function in formulae, you must configure an -HTTP client. Assuming you chose Guzzle 7, this can be done like: - - -```php -use GuzzleHttp\Client; -use Http\Factory\Guzzle\RequestFactory; -use PhpOffice\PhpSpreadsheet\Settings; - -$client = new Client(); -$requestFactory = new RequestFactory(); - -Settings::setHttpClient($client, $requestFactory); -``` +Formulae](./recipes.md#locale-settings-for-formulae). diff --git a/docs/topics/tables.md b/docs/topics/tables.md deleted file mode 100644 index a16d036bf4..0000000000 --- a/docs/topics/tables.md +++ /dev/null @@ -1,16 +0,0 @@ -# Tables - -## Introduction - -To make managing and analyzing a group of related data easier, you can turn a range of cells into an Excel table (previously known as an Excel list). - -## Support - -Currently tables are supported in Xlsx reader and Html Writer - -To enable table formatting for Html writer, use: - -```php - $writer = new HtmlWriter($spreadsheet); - $writer->setConditionalFormatting(true); -``` \ No newline at end of file diff --git a/docs/topics/worksheets.md b/docs/topics/worksheets.md index 5b15089b61..f97a00665d 100644 --- a/docs/topics/worksheets.md +++ b/docs/topics/worksheets.md @@ -25,7 +25,7 @@ each worksheet "tab" is shown when the workbook is opened in MS Excel (or other appropriate Spreadsheet program). To access a sheet by its index, use the `getSheet()` method. -```php +``` php // Get the second sheet in the workbook // Note that sheets are indexed from 0 $spreadsheet->getSheet(1); @@ -38,7 +38,7 @@ workbook. To access a sheet by name, use the `getSheetByName()` method, specifying the name of the worksheet that you want to access. -```php +``` php // Retrieve the worksheet called 'Worksheet 1' $spreadsheet->getSheetByName('Worksheet 1'); ``` @@ -48,7 +48,7 @@ and you can access that directly. The currently active worksheet is the one that will be active when the workbook is opened in MS Excel (or other appropriate Spreadsheet program). -```php +``` php // Retrieve the current active worksheet $spreadsheet->getActiveSheet(); ``` @@ -64,7 +64,7 @@ a new "last" sheet; but you can also specify an index position as an argument, and the worksheet will be inserted at that position, shuffling all subsequent worksheets in the collection down a place. -```php +``` php $spreadsheet->createSheet(); ``` @@ -76,7 +76,7 @@ Alternatively, you can instantiate a new worksheet (setting the title to whatever you choose) and then insert it into your workbook using the `addSheet()` method. -```php +``` php // Create a new worksheet called "My Data" $myWorkSheet = new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'My Data'); @@ -93,40 +93,21 @@ Sheets within the same workbook can be copied by creating a clone of the worksheet you wish to copy, and then using the `addSheet()` method to insert the clone into the workbook. -```php +``` php $clonedWorksheet = clone $spreadsheet->getSheetByName('Worksheet 1'); -$clonedWorksheet->setTitle('Copy of Worksheet 1'); // must be unique +$clonedWorksheet->setTitle('Copy of Worksheet 1'); $spreadsheet->addSheet($clonedWorksheet); ``` -Starting with PhpSpreadsheet 3.9.0, this can be done more simply (copied sheet's title will be set to something unique): -```php -$copiedWorksheet = $spreadsheet->duplicateWorksheetByTitle('sheetname'); -``` You can also copy worksheets from one workbook to another, though this is more complex as PhpSpreadsheet also has to replicate the styling between the two workbooks. The `addExternalSheet()` method is provided for this purpose. -```php -$clonedWorksheet = clone $spreadsheet1->getSheetByName('Worksheet 1'); -$clonedWorksheet->setTitle('Copy of Worksheet 1'); // must be unique -$spreadsheet1->addSheet($clonedWorksheet); -$spreadsheet->addExternalSheet($clonedWorksheet); -``` -Starting with PhpSpreadsheet 3.8.0, this can be simplified: -```php -$clonedWorksheet = clone $spreadsheet1->getSheetByName('Worksheet 1'); -$spreadsheet1->addSheet($clonedWorksheet, null, true); -$spreadsheet->addExternalSheet($clonedWorksheet); -``` -Starting with PhpSpreadsheet 3.9.0, this can be simplified even further: -```php -$clonedWorksheet = $spreadsheet1->duplicateWorksheetByTitle('sheetname'); -$spreadsheet->addExternalSheet($clonedWorksheet); -``` + $clonedWorksheet = clone $spreadsheet1->getSheetByName('Worksheet 1'); + $spreadsheet->addExternalSheet($clonedWorksheet); -In the cases commented "must be unique", it is the developer's responsibility to ensure that +In both cases, it is the developer's responsibility to ensure that worksheet names are not duplicated. PhpSpreadsheet will throw an exception if you attempt to copy worksheets that will result in a duplicate name. @@ -136,7 +117,7 @@ duplicate name. You can delete a worksheet from a workbook, identified by its index position, using the `removeSheetByIndex()` method -```php +``` php $sheetIndex = $spreadsheet->getIndex( $spreadsheet->getSheetByName('Worksheet 1') ); diff --git a/infra/DocumentGenerator.php b/infra/DocumentGenerator.php deleted file mode 100644 index 85467da911..0000000000 --- a/infra/DocumentGenerator.php +++ /dev/null @@ -1,141 +0,0 @@ - $phpSpreadsheetFunctions - */ - public static function generateFunctionListByCategory($phpSpreadsheetFunctions): string - { - $result = "# Function list by category\n"; - foreach (self::getCategories() as $categoryConstant => $category) { - $result .= "\n"; - $result .= "## {$categoryConstant}\n"; - $result .= "\n"; - $lengths = [25, 37]; - $result .= self::tableRow($lengths, ['Excel Function', 'PhpSpreadsheet Function']) . "\n"; - $result .= self::tableRow($lengths, null) . "\n"; - foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) { - if (in_array($excelFunction, self::EXCLUDED_FUNCTIONS, true)) { - continue; - } - if ($category === $functionInfo['category']) { - $phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']); - $result .= self::tableRow($lengths, [$excelFunction, $phpFunction]) . "\n"; - } - } - } - - return $result; - } - - /** @return array */ - private static function getCategories(): array - { - /** @var array */ - $x = (new ReflectionClass(Category::class))->getConstants(); - - return $x; - } - - /** - * @param int[] $lengths - * @param null|array $values - */ - private static function tableRow(array $lengths, ?array $values = null): string - { - $result = ''; - foreach (array_map(null, $lengths, $values ?? []) as $i => [$length, $value]) { - $pad = $value === null ? '-' : ' '; - if ($i > 0) { - $result .= '|' . $pad; - } - $result .= str_pad("$value", $length ?? 0, $pad); - } - - return rtrim($result, ' '); - } - - /** @param scalar|string|string[] $functionCall */ - private static function getPhpSpreadsheetFunctionText(mixed $functionCall): string - { - if (is_string($functionCall)) { - return $functionCall; - } - if ($functionCall === [Functions::class, 'DUMMY']) { - return '**Not yet Implemented**'; - } - if (is_array($functionCall)) { - return "\\{$functionCall[0]}::{$functionCall[1]}"; - } - - throw new UnexpectedValueException( - '$functionCall is of type ' . gettype($functionCall) . '. string or array expected' - ); - } - - /** - * @param array $phpSpreadsheetFunctions - */ - public static function generateFunctionListByName(array $phpSpreadsheetFunctions, bool $compact = false): string - { - $categoryConstants = array_flip(self::getCategories()); - if ($compact) { - $result = "# Function list by name compact\n"; - $result .= "\n"; - $result .= 'Category should be prefixed by `CATEGORY_` to match the values in \PhpOffice\PhpSpreadsheet\Calculation\Category'; - $result .= "\n\n"; - $result .= 'Function should be prefixed by `PhpOffice\PhpSpreadsheet\Calculation\`'; - $result .= "\n\n"; - $result .= 'A less compact list can be found [here](./function-list-by-name.md)'; - $result .= "\n\n"; - } else { - $result = "# Function list by name\n"; - $result .= "\n"; - $result .= 'A more compact list can be found [here](./function-list-by-name-compact.md)'; - $result .= "\n\n"; - } - $lastAlphabet = null; - $lengths = $compact ? [25, 22, 37] : [25, 31, 37]; - foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) { - if (in_array($excelFunction, self::EXCLUDED_FUNCTIONS, true)) { - continue; - } - if ($lastAlphabet !== $excelFunction[0]) { - $lastAlphabet = $excelFunction[0]; - $result .= "\n"; - $result .= "## {$lastAlphabet}\n"; - $result .= "\n"; - $result .= self::tableRow($lengths, ['Excel Function', 'Category', 'PhpSpreadsheet Function']) . "\n"; - $result .= self::tableRow($lengths, null) . "\n"; - } - $category = $categoryConstants[$functionInfo['category']]; - $phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']); - if ($compact) { - $category = str_replace('CATEGORY_', '', $category); - $phpFunction = str_replace( - '\PhpOffice\PhpSpreadsheet\Calculation\\', - '', - $phpFunction - ); - } - $result .= self::tableRow($lengths, [$excelFunction, $category, $phpFunction]) . "\n"; - } - - return $result; - } -} diff --git a/infra/LocaleGenerator.php b/infra/LocaleGenerator.php deleted file mode 100644 index 7440306777..0000000000 --- a/infra/LocaleGenerator.php +++ /dev/null @@ -1,383 +0,0 @@ - */ - protected array $phpSpreadsheetFunctions; - - protected Spreadsheet $translationSpreadsheet; - - protected bool $verbose; - - protected Worksheet $localeTranslations; - - /** @var string[] */ - protected array $localeLanguageMap = []; - - /** @var int[] */ - protected array $errorCodeMap = []; - - private Worksheet $functionNameTranslations; - - /** @var string[] */ - protected array $functionNameLanguageMap = []; - - /** @var array */ - protected array $functionNameMap = []; - - /** - * @param array $phpSpreadsheetFunctions - */ - public function __construct( - string $translationBaseFolder, - string $translationSpreadsheetName, - array $phpSpreadsheetFunctions, - bool $verbose = false - ) { - $this->translationBaseFolder = $translationBaseFolder; - $this->translationSpreadsheetName = $translationSpreadsheetName; - $this->phpSpreadsheetFunctions = $phpSpreadsheetFunctions; - $this->verbose = $verbose; - } - - public function generateLocales(): void - { - $this->openTranslationWorkbook(); - - $this->localeTranslations = $this->getTranslationSheet(self::EXCEL_LOCALISATION_WORKSHEET); - $this->localeLanguageMap = $this->mapLanguageColumns($this->localeTranslations); - $this->mapErrorCodeRows(); - - $this->functionNameTranslations = $this->getTranslationSheet(self::EXCEL_FUNCTIONS_WORKSHEET); - $this->functionNameLanguageMap = $this->mapLanguageColumns($this->functionNameTranslations); - $this->mapFunctionNameRows(); - - foreach ($this->localeLanguageMap as $column => $locale) { - $this->buildConfigFileForLocale($column, $locale); - } - - foreach ($this->functionNameLanguageMap as $column => $locale) { - $this->buildFunctionsFileForLocale($column, $locale); - } - } - - protected function buildConfigFileForLocale(string $column, string $locale): void - { - $language = $this->localeTranslations->getCell($column . self::ENGLISH_LANGUAGE_NAME_ROW)->getValue(); - if (!is_string($language)) { - throw new Exception('Non-string language value at ' . $column . self::ENGLISH_LANGUAGE_NAME_ROW); - } - $localeLanguage = $this->localeTranslations->getCell($column . self::LOCALE_LANGUAGE_NAME_ROW)->getValue(); - if (!is_string($localeLanguage)) { - throw new Exception('Non-string locale language value at ' . $column . self::LOCALE_LANGUAGE_NAME_ROW); - } - $configFile = $this->openConfigFile($locale, $language, $localeLanguage); - - $this->writeConfigArgumentSeparator($configFile, $column); - $this->writeConfigCurrencySymbol($configFile, $column); - $this->writeFileSectionHeader($configFile, 'Error Codes'); - - foreach ($this->errorCodeMap as $errorCode => $row) { - $translationCell = $this->localeTranslations->getCell($column . $row); - $translationValue = $translationCell->getValue(); - if ($translationValue !== null && !is_string($translationValue)) { - throw new Exception('Non-string translation value at ' . $column . $row); - } - if (!empty($translationValue)) { - $errorCodeTranslation = "{$errorCode} = {$translationValue}" . self::EOL; - fwrite($configFile, $errorCodeTranslation); - } else { - $errorCodeTranslation = "{$errorCode}" . self::EOL; - fwrite($configFile, $errorCodeTranslation); - $this->log("No {$language} translation available for error code {$errorCode}"); - } - } - - fclose($configFile); - } - - /** @param resource $configFile resource to write to */ - protected function writeConfigArgumentSeparator($configFile, string $column): void - { - $translationCell = $this->localeTranslations->getCell($column . self::ARGUMENT_SEPARATOR_ROW); - $localeValue = $translationCell->getValue(); - if ($localeValue !== null && !is_string($localeValue)) { - throw new Exception('Non-string locale value at ' . $column . self::CURRENCY_SYMBOL_ROW); - } - if (!empty($localeValue)) { - $functionTranslation = "ArgumentSeparator = {$localeValue}" . self::EOL; - fwrite($configFile, $functionTranslation); - } else { - $this->log('No Argument Separator defined'); - } - } - - /** @param resource $configFile resource to write to */ - protected function writeConfigCurrencySymbol($configFile, string $column): void - { - $translationCell = $this->localeTranslations->getCell($column . self::CURRENCY_SYMBOL_ROW); - $localeValue = $translationCell->getValue(); - if ($localeValue !== null && !is_string($localeValue)) { - throw new Exception('Non-string locale value at ' . $column . self::CURRENCY_SYMBOL_ROW); - } - if (!empty($localeValue)) { - $functionTranslation = "currencySymbol = {$localeValue}" . self::EOL; - fwrite($configFile, '##' . self::EOL); - fwrite($configFile, '## (For future use)' . self::EOL); - fwrite($configFile, '##' . self::EOL); - fwrite($configFile, $functionTranslation); - } else { - $this->log('No Currency Symbol defined'); - } - } - - protected function buildFunctionsFileForLocale(string $column, string $locale): void - { - $language = $this->functionNameTranslations->getCell($column . self::ENGLISH_LANGUAGE_NAME_ROW)->getValue(); - if (!is_string($language)) { - throw new Exception('Non-string language value at ' . $column . self::ENGLISH_LANGUAGE_NAME_ROW); - } - $localeLanguage = $this->functionNameTranslations->getCell($column . self::LOCALE_LANGUAGE_NAME_ROW) - ->getValue(); - if (!is_string($localeLanguage)) { - throw new Exception('Non-string locale language value at ' . $column . self::LOCALE_LANGUAGE_NAME_ROW); - } - $functionFile = $this->openFunctionNameFile($locale, $language, $localeLanguage); - - foreach ($this->functionNameMap as $functionName => $row) { - $translationCell = $this->functionNameTranslations->getCell($column . $row); - $translationValue = $translationCell->getValue(); - if ($translationValue !== null && !is_string($translationValue)) { - throw new Exception('Non-string translation value at ' . $column . $row); - } - if ($this->isFunctionCategoryEntry($translationCell)) { - $this->writeFileSectionHeader($functionFile, "{$translationValue} ({$functionName})"); - } elseif (!array_key_exists($functionName, $this->phpSpreadsheetFunctions) && substr($functionName, 0, 1) !== '*') { - $this->log("Function {$functionName} is not defined in PhpSpreadsheet"); - } elseif (!empty($translationValue)) { - $functionTranslation = "{$functionName} = {$translationValue}" . self::EOL; - fwrite($functionFile, $functionTranslation); - } else { - $this->log("No {$language} translation available for function {$functionName}"); - } - } - - fclose($functionFile); - } - - /** @return resource used by other methods in this class */ - protected function openConfigFile(string $locale, string $language, string $localeLanguage) - { - $this->log("Building locale {$locale} ($language) configuration"); - $localeFolder = $this->getLocaleFolder($locale); - - $configFileName = realpath($localeFolder) . DIRECTORY_SEPARATOR . 'config'; - $this->log("Writing locale configuration to {$configFileName}"); - - $configFile = fopen($configFileName, 'wb'); - if ($configFile === false) { - throw new Exception('Unable to open $configFileName for write'); - } - $this->writeFileHeader($configFile, $localeLanguage, $language, 'locale settings'); - - return $configFile; - } - - /** @return resource used by other methods in this class */ - protected function openFunctionNameFile(string $locale, string $language, string $localeLanguage) - { - $this->log("Building locale {$locale} ($language) function names"); - $localeFolder = $this->getLocaleFolder($locale); - - $functionFileName = realpath($localeFolder) . DIRECTORY_SEPARATOR . 'functions'; - $this->log("Writing local function names to {$functionFileName}"); - - $functionFile = fopen($functionFileName, 'wb'); - if ($functionFile === false) { - throw new Exception('Unable to open $functionFileName for write'); - } - $this->writeFileHeader($functionFile, $localeLanguage, $language, 'function name translations'); - - return $functionFile; - } - - protected function getLocaleFolder(string $locale): string - { - $lastchar = substr($this->translationBaseFolder, -1); - $dirsep = ($lastchar === '/' || $lastchar === '\\') ? '' : DIRECTORY_SEPARATOR; - $localeFolder = $this->translationBaseFolder - . $dirsep - . str_replace('_', DIRECTORY_SEPARATOR, $locale); - if (!file_exists($localeFolder) || !is_dir($localeFolder)) { - mkdir($localeFolder, 7 * 64 + 7 * 8 + 7, true); // octal 777 - } - - return $localeFolder; - } - - /** @param resource $localeFile file being written to */ - protected function writeFileHeader($localeFile, string $localeLanguage, string $language, string $title): void - { - fwrite($localeFile, str_repeat('#', 60) . self::EOL); - fwrite($localeFile, '##' . self::EOL); - fwrite($localeFile, "## PhpSpreadsheet - {$title}" . self::EOL); - fwrite($localeFile, '##' . self::EOL); - fwrite($localeFile, "## {$localeLanguage} ({$language})" . self::EOL); - fwrite($localeFile, '##' . self::EOL); - fwrite($localeFile, str_repeat('#', 60) . self::EOL . self::EOL); - } - - /** @param resource $localeFile file being written to */ - protected function writeFileSectionHeader($localeFile, string $header): void - { - fwrite($localeFile, self::EOL . '##' . self::EOL); - fwrite($localeFile, "## {$header}" . self::EOL); - fwrite($localeFile, '##' . self::EOL); - } - - protected function openTranslationWorkbook(): void - { - $filepathName = $this->translationBaseFolder . '/' . $this->translationSpreadsheetName; - $this->translationSpreadsheet = IOFactory::load($filepathName); - } - - protected function getTranslationSheet(string $sheetName): Worksheet - { - $worksheet = $this->translationSpreadsheet->setActiveSheetIndexByName($sheetName); - - return $worksheet; - } - - /** @return string[] */ - protected function mapLanguageColumns(Worksheet $translationWorksheet): array - { - $sheetName = $translationWorksheet->getTitle(); - $this->log("Mapping Languages for {$sheetName}:"); - - $baseColumn = self::ENGLISH_REFERENCE_COLUMN; - $languagesList = $translationWorksheet->getColumnIterator(++$baseColumn); - - $languageNameMap = []; - foreach ($languagesList as $languageColumn) { - $cells = $languageColumn->getCellIterator(self::LOCALE_NAME_ROW, self::LOCALE_NAME_ROW); - $cells->setIterateOnlyExistingCells(true); - foreach ($cells as $cell) { - if ($this->localeCanBeSupported($translationWorksheet, $cell)) { - $languageNameMap[$cell->getColumn()] = $cell->getValueString(); - $this->log($cell->getColumn() . ' -> ' . $cell->getValueString()); - } - } - } - - return $languageNameMap; - } - - protected function localeCanBeSupported(Worksheet $worksheet, Cell $cell): bool - { - if ($worksheet->getTitle() === self::EXCEL_LOCALISATION_WORKSHEET) { - // Only provide support for languages that have a function argument separator defined - // in the localisation worksheet - return !empty( - $worksheet->getCell($cell->getColumn() . self::ARGUMENT_SEPARATOR_ROW)->getValue() - ); - } - - // If we're processing other worksheets, then language support is determined by whether we included the - // language in the map when we were processing the localisation worksheet (which is always processed first) - return in_array($cell->getValue(), $this->localeLanguageMap, true); - } - - protected function mapErrorCodeRows(): void - { - $this->log('Mapping Error Codes:'); - $errorList = $this->localeTranslations->getRowIterator(self::ERROR_CODES_FIRST_ROW); - - foreach ($errorList as $errorRow) { - $cells = $errorRow->getCellIterator(self::ENGLISH_REFERENCE_COLUMN, self::ENGLISH_REFERENCE_COLUMN); - $cells->setIterateOnlyExistingCells(true); - foreach ($cells as $cell) { - if ($cell->getValue() != '') { - $this->log($cell->getRow() . ' -> ' . $cell->getValueString()); - $this->errorCodeMap[$cell->getValue()] = $cell->getRow(); - } - } - } - } - - protected function mapFunctionNameRows(): void - { - $this->log('Mapping Functions:'); - $functionList = $this->functionNameTranslations->getRowIterator(self::FUNCTION_NAME_LIST_FIRST_ROW); - - foreach ($functionList as $functionRow) { - $cells = $functionRow->getCellIterator(self::ENGLISH_REFERENCE_COLUMN, self::ENGLISH_REFERENCE_COLUMN); - $cells->setIterateOnlyExistingCells(true); - foreach ($cells as $cell) { - if ($this->isFunctionCategoryEntry($cell)) { - if (!empty($cell->getValue())) { - $this->log('CATEGORY: ' . $cell->getValueString()); - $this->functionNameMap[$cell->getValue()] = $cell->getRow(); - } - - continue; - } - if ($cell->getValue() !== '' && $cell->getValue() !== null) { - if (is_bool($cell->getValue())) { - $this->log($cell->getRow() . ' -> ' . ($cell->getValue() ? 'TRUE' : 'FALSE')); - $this->functionNameMap[($cell->getValue() ? 'TRUE' : 'FALSE')] = $cell->getRow(); - } else { - $this->log($cell->getRow() . ' -> ' . $cell->getValueString()); - $this->functionNameMap[$cell->getValue()] = $cell->getRow(); - } - } - } - } - } - - private function isFunctionCategoryEntry(Cell $cell): bool - { - $categoryCheckCell = self::ENGLISH_FUNCTION_CATEGORIES_COLUMN . $cell->getRow(); - if ($this->functionNameTranslations->getCell($categoryCheckCell)->getValue() != '') { - return true; - } - - return false; - } - - private function log(string $message): void - { - if ($this->verbose === false) { - return; - } - - echo $message, self::EOL; - } -} diff --git a/mkdocs.yml b/mkdocs.yml index d382c6385c..1a224f5c8b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,7 @@ site_name: PhpSpreadsheet Documentation repo_url: https://github.com/PHPOffice/phpspreadsheet -edit_uri: edit/master/docs/ +edit_uri: edit/develop/docs/ theme: readthedocs extra_css: - extra/extra.css -extra_javascript: - - extra/extrajs.js -markdown_extensions: - - md_in_html diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index 29bdc49fa0..0000000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,49 +0,0 @@ -parameters: - ignoreErrors: - - - message: '#^Parameter \#1 \$array of function array_multisort expects array, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/PhpSpreadsheet/Calculation/LookupRef/Sort.php - - - - message: '#^Cannot call method getAllSpContainers\(\) on mixed\.$#' - identifier: method.nonObject - count: 1 - path: src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php - - - - message: '#^Cannot call method getBSECollection\(\) on mixed\.$#' - identifier: method.nonObject - count: 1 - path: src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php - - - - message: '#^Cannot call method getBstoreContainer\(\) on mixed\.$#' - identifier: method.nonObject - count: 1 - path: src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php - - - - message: '#^Cannot call method getSpgrContainer\(\) on mixed\.$#' - identifier: method.nonObject - count: 1 - path: src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php - - - - message: '#^Cannot access offset 0 on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: '#^Parameter \#1 \$string of function trim expects string, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/PhpSpreadsheet/ReferenceHelper.php - - - - message: '#^Cannot call method setParent\(\) on mixed\.$#' - identifier: method.nonObject - count: 1 - path: src/PhpSpreadsheet/Worksheet/AutoFilter.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist deleted file mode 100644 index 73ef676c73..0000000000 --- a/phpstan.neon.dist +++ /dev/null @@ -1,33 +0,0 @@ -includes: - - phpstan-baseline.neon - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon - - vendor/composer/pcre/extension.neon - - vendor/phpstan/phpstan/conf/bleedingEdge.neon - - vendor/phpstan/phpstan-deprecation-rules/rules.neon - -parameters: - level: 10 - paths: - - samples/ - - src/ - - tests/ - - infra/ - - bin/ - excludePaths: - - src/PhpSpreadsheet/Chart/Renderer/JpGraph.php - - src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php - - src/PhpSpreadsheet/Collection/Memory/SimpleCache1.php - - src/PhpSpreadsheet/Collection/Memory/SimpleCache3.php - - src/PhpSpreadsheet/Writer/ZipStream2.php - - src/PhpSpreadsheet/Writer/ZipStream3.php - - tests/PhpSpreadsheetTests/Writer/Xlsx/ArrayFunctions2Test.php - parallel: - processTimeout: 300.0 - ignoreErrors: - # Accept a bit anything for assert methods - - '~^Parameter \#2 .* of static method PHPUnit\\Framework\\Assert\:\:assert\w+\(\) expects .*, .* given\.$~' - - '~Method .*rovider.* return type has no value type specified in iterable type array\.$~' - - '~Method .*rovider.* should return array but returns mixed\.$~' - - '~.* has parameter \$expectedResult with no value type specified in iterable type array\.$~' - #- identifier: missingType.iterableValue diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d3e845c1ea..6880d23e48 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,22 @@ - - - - - - - - ./tests/PhpSpreadsheetTests - - - - ./src - - + + + + + + ./tests/PhpSpreadsheetTests + + + + ./src + + ./src/PhpSpreadsheet/Shared/JAMA + ./src/PhpSpreadsheet/Writer/PDF + + + diff --git a/samples/Autofilter/10_Autofilter.php b/samples/Autofilter/10_Autofilter.php index 4002f1806b..db9de54aa4 100644 --- a/samples/Autofilter/10_Autofilter.php +++ b/samples/Autofilter/10_Autofilter.php @@ -3,7 +3,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -86,19 +85,17 @@ ['2011', 'Q4', 'Italy', 335], ]; $spreadsheet->getActiveSheet()->fromArray($dataArray, null, 'A2'); -$helper->displayGrid($spreadsheet->getActiveSheet()->toArray(null, false, false, true)); // Set title row bold $helper->log('Set title row bold'); $spreadsheet->getActiveSheet()->getStyle('A1:D1')->getFont()->setBold(true); // Set autofilter -$filterRange = $spreadsheet->getActiveSheet()->calculateWorksheetDimension(); -$helper->log("Set autofilter for cells {$filterRange}"); -// Always include the complete filter range if you can! +$helper->log('Set autofilter'); +// Always include the complete filter range! // Excel does support setting only the caption // row, but that's not a best practise... -$spreadsheet->getActiveSheet()->setAutoFilter($filterRange); +$spreadsheet->getActiveSheet()->setAutoFilter($spreadsheet->getActiveSheet()->calculateWorksheetDimension()); // Save -$helper->write($spreadsheet, __FILE__, ['Xlsx']); +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Autofilter/10_Autofilter_dynamic_dates.php b/samples/Autofilter/10_Autofilter_dynamic_dates.php deleted file mode 100644 index 54ec63b018..0000000000 --- a/samples/Autofilter/10_Autofilter_dynamic_dates.php +++ /dev/null @@ -1,112 +0,0 @@ -log('Add data'); - - $sheet = $spreadsheet->createSheet(); - $sheet->setTitle($rule); - $sheet->getCell('A1')->setValue('Date'); - $row = 1; - $date = new DateTime(); - $year = (int) $date->format('Y'); - $month = (int) $date->format('m'); - $day = (int) $date->format('d'); - $yearMinus2 = $year - 2; - $sheet->getCell('B1')->setValue("=DATE($year, $month, $day)"); - // Each day for two weeks before today through 2 weeks after - for ($dayOffset = -14; $dayOffset < 14; ++$dayOffset) { - ++$row; - $sheet->getCell("A$row")->setValue("=B1+($dayOffset)"); - } - // First and last day of each month, starting with January 2 years before, - // through December 2 years after. - for ($monthOffset = 0; $monthOffset < 48; ++$monthOffset) { - ++$row; - $sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset, 1)"); - ++$row; - $sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset + 1, 0)"); - } - $sheet->getStyle("A2:A$row")->getNumberFormat()->setFormatCode('yyyy-mm-dd'); - $sheet->getStyle('B1')->getNumberFormat()->setFormatCode('yyyy-mm-dd'); - $sheet->getColumnDimension('A')->setAutoSize(true); - $sheet->getColumnDimension('B')->setAutoSize(true); - - if ($displayInitialWorksheet) { - $helper->log('Unfiltered Dates'); - $helper->displayGrid($sheet->toArray(null, true, true, true)); - } - - $helper->log("Filter for $rule"); - $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); - $autoFilter->setRange("A1:A{$row}"); - $columnFilter = $autoFilter->getColumn('A'); - $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); - $columnFilter->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, '', $rule) - ->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER); - $sheet->setSelectedCell('B1'); - - $helper->log('Execute filtering (apply the filter rules)'); - $autoFilter->showHideRows(); - - $helper->log('Filtered Dates'); - $helper->displayGrid($sheet->toArray(null, true, true, true, true)); -} - -// Create new Spreadsheet object -/** @var Sample $helper */ -$helper->log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Owen Leibman') - ->setLastModifiedBy('Owen Leibman') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -$ruleNames = [ - Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2, - Rule::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3, -]; - -// Create the worksheets -foreach ($ruleNames as $index => $ruleName) { - createSheet($helper, $spreadsheet, $ruleName, $index === 0); -} -$spreadsheet->removeSheetByIndex(0); -$spreadsheet->setActiveSheetIndex(0); -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Autofilter/10_Autofilter_selection_1.php b/samples/Autofilter/10_Autofilter_selection_1.php index ce1bcd435e..30efc19411 100644 --- a/samples/Autofilter/10_Autofilter_selection_1.php +++ b/samples/Autofilter/10_Autofilter_selection_1.php @@ -7,7 +7,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -32,8 +31,7 @@ ->setCellValue('D1', 'Date') ->setCellValue('E1', 'Sales Value') ->setCellValue('F1', 'Expenditure'); -$dateTime = new DateTime(); -$startYear = $endYear = $currentYear = (int) $dateTime->format('Y'); +$startYear = $endYear = $currentYear = date('Y'); --$startYear; ++$endYear; @@ -54,27 +52,25 @@ foreach ($years as $year) { foreach ($periods as $period) { foreach ($countries as $country) { - $dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period); - $dateTime = new DateTime($dateString); - $endDays = (int) $dateTime->format('t'); + $endDays = date('t', mktime(0, 0, 0, $period, 1, $year)); for ($i = 1; $i <= $endDays; ++$i) { $eDate = Date::formattedPHPToExcel( $year, $period, $i ); - $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $value = rand(500, 1000) * (1 + rand(-0.25, +0.25)); $salesValue = $invoiceValue = null; - $incomeOrExpenditure = mt_rand(-1, 1); + $incomeOrExpenditure = rand(-1, 1); if ($incomeOrExpenditure == -1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); $income = null; } elseif ($incomeOrExpenditure == 1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } else { $expenditure = null; - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } $dataArray = [$year, $period, @@ -96,47 +92,42 @@ $spreadsheet->getActiveSheet()->getStyle('A1:F1')->getAlignment()->setWrapText(true); $spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(12.5); $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(10.5); -$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD); -$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_INTEGER); +$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD2); +$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); $spreadsheet->getActiveSheet()->getColumnDimension('F')->setWidth(14); $spreadsheet->getActiveSheet()->freezePane('A2'); -$helper->displayGrid($spreadsheet->getActiveSheet()->toArray(null, false, true, true)); - // Set autofilter range -$filterRange = $spreadsheet->getActiveSheet()->calculateWorksheetDimension(); -$helper->log("Set autofilter for cells {$filterRange}"); -// Always include the complete filter range if you can! -// Excel does support setting only the caption row, but that's not a best practise... -$spreadsheet->getActiveSheet()->setAutoFilter($filterRange); +$helper->log('Set autofilter range'); +// Always include the complete filter range! +// Excel does support setting only the caption +// row, but that's not a best practise... +$spreadsheet->getActiveSheet()->setAutoFilter($spreadsheet->getActiveSheet()->calculateWorksheetDimension()); // Set active filters $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); $helper->log('Set active filters'); - // Filter the Country column on a filter value of countries beginning with the letter U (or Japan) // We use * as a wildcard, so specify as U* and using a wildcard requires customFilter $autoFilter->getColumn('C') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'u*') + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + 'u*' + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); - -$helper->log('Set country code filter (Column C) to countries beginning with "U" ("United States" and "UK")'); - $autoFilter->getColumn('C') ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'japan') + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + 'japan' + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); - -$helper->log('Add "Japan" to the country code filter (Column C)'); - -// Filter the Date column on a filter value of the last day of every period of the current year -// We use a dateGroup ruletype for this, although it is still a standard filter +// Filter the Date column on a filter value of the first day of every period of the current year +// We us a dateGroup ruletype for this, although it is still a standard filter foreach ($periods as $period) { - $dateString = sprintf('%04d-%02d-01T00:00:00', $currentYear, $period); - $dateTime = new DateTime($dateString); - $endDate = (int) $dateTime->format('t'); + $endDate = date('t', mktime(0, 0, 0, $period, 1, $currentYear)); $autoFilter->getColumn('D') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER) @@ -151,20 +142,15 @@ ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_DATEGROUP); } - -$helper->log('Add filter on the Date (Column D) to display only rows for the last day of each month'); - // Display only sales values that are blank -// Standard filter, operator equals, and value of NULL or empty space +// Standard filter, operator equals, and value of NULL $autoFilter->getColumn('E') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, ''); - -$helper->log('Add filter on Sales Values (Column E) to display only blank values'); - -$helper->log('NOTE: We don\'t apply the filter rules in this example, so we can\'t see the result here; although Excel will apply the rules when the file is loaded'); -$helper->log('See 10_Autofilter_selection_display.php for an example that actually executes the filter rules'); + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + '' + ); // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/Autofilter/10_Autofilter_selection_2.php b/samples/Autofilter/10_Autofilter_selection_2.php index 456f149f08..1520c972b3 100644 --- a/samples/Autofilter/10_Autofilter_selection_2.php +++ b/samples/Autofilter/10_Autofilter_selection_2.php @@ -7,7 +7,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -32,8 +31,7 @@ ->setCellValue('D1', 'Date') ->setCellValue('E1', 'Sales Value') ->setCellValue('F1', 'Expenditure'); -$dateTime = new DateTime(); -$startYear = $endYear = $currentYear = (int) $dateTime->format('Y'); +$startYear = $endYear = $currentYear = date('Y'); --$startYear; ++$endYear; @@ -54,27 +52,25 @@ foreach ($years as $year) { foreach ($periods as $period) { foreach ($countries as $country) { - $dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period); - $dateTime = new DateTime($dateString); - $endDays = (int) $dateTime->format('t'); + $endDays = date('t', mktime(0, 0, 0, $period, 1, $year)); for ($i = 1; $i <= $endDays; ++$i) { $eDate = Date::formattedPHPToExcel( $year, $period, $i ); - $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $value = rand(500, 1000) * (1 + rand(-0.25, +0.25)); $salesValue = $invoiceValue = null; - $incomeOrExpenditure = mt_rand(-1, 1); + $incomeOrExpenditure = rand(-1, 1); if ($incomeOrExpenditure == -1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); $income = null; } elseif ($incomeOrExpenditure == 1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } else { $expenditure = null; - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } $dataArray = [$year, $period, @@ -96,59 +92,57 @@ $spreadsheet->getActiveSheet()->getStyle('A1:F1')->getAlignment()->setWrapText(true); $spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(12.5); $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(10.5); -$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD); -$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_INTEGER); +$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD2); +$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); $spreadsheet->getActiveSheet()->getColumnDimension('F')->setWidth(14); $spreadsheet->getActiveSheet()->freezePane('A2'); -$helper->displayGrid($spreadsheet->getActiveSheet()->toArray(null, false, true, true)); - // Set autofilter range -$filterRange = $spreadsheet->getActiveSheet()->calculateWorksheetDimension(); -$helper->log("Set autofilter for cells {$filterRange}"); -// Always include the complete filter range if you can! -// Excel does support setting only the caption row, but that's not a best practise... -$spreadsheet->getActiveSheet()->setAutoFilter($filterRange); +$helper->log('Set autofilter range'); +// Always include the complete filter range! +// Excel does support setting only the caption +// row, but that's not a best practise... +$spreadsheet->getActiveSheet()->setAutoFilter($spreadsheet->getActiveSheet()->calculateWorksheetDimension()); // Set active filters $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); $helper->log('Set active filters'); - // Filter the Country column on a filter value of Germany // As it's just a simple value filter, we can use FILTERTYPE_FILTER $autoFilter->getColumn('C') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'Germany'); - -$helper->log('Set country code filter (Column C) to "Germany"'); - + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + 'Germany' + ); // Filter the Date column on a filter value of the year to date $autoFilter->getColumn('D') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, '', Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE) + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + null, + Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER); - -$helper->log('Add filter on the Date (Column D) to display year to date'); - // Display only sales values that are between 400 and 600 $autoFilter->getColumn('E') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 400) + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, + 400 + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); - $autoFilter->getColumn('E') ->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL, 600) + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL, + 600 + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); -$helper->log('Add filter on Sales Values (Column E) between 400 and 600'); - -$helper->log('NOTE: We don\'t apply the filter rules in this example, so we can\'t see the result here; although Excel will apply the rules when the file is loaded'); -$helper->log('See 10_Autofilter_selection_display.php for an example that actually executes the filter rules inside PhpSpreadsheet'); - // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/Autofilter/10_Autofilter_selection_display.php b/samples/Autofilter/10_Autofilter_selection_display.php index c2d8f871c6..50986bfa5b 100644 --- a/samples/Autofilter/10_Autofilter_selection_display.php +++ b/samples/Autofilter/10_Autofilter_selection_display.php @@ -7,7 +7,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -32,8 +31,7 @@ ->setCellValue('D1', 'Date') ->setCellValue('E1', 'Sales Value') ->setCellValue('F1', 'Expenditure'); -$dateTime = new DateTime(); -$startYear = $endYear = $currentYear = (int) $dateTime->format('Y'); +$startYear = $endYear = $currentYear = date('Y'); --$startYear; ++$endYear; @@ -54,27 +52,25 @@ foreach ($years as $year) { foreach ($periods as $period) { foreach ($countries as $country) { - $dateString = sprintf('%04d-%02d-01T00:00:00', $year, $period); - $dateTime = new DateTime($dateString); - $endDays = (int) $dateTime->format('t'); + $endDays = date('t', mktime(0, 0, 0, $period, 1, $year)); for ($i = 1; $i <= $endDays; ++$i) { $eDate = Date::formattedPHPToExcel( $year, $period, $i ); - $value = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $value = rand(500, 1000) * (1 + rand(-0.25, +0.25)); $salesValue = $invoiceValue = null; - $incomeOrExpenditure = mt_rand(-1, 1); + $incomeOrExpenditure = rand(-1, 1); if ($incomeOrExpenditure == -1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); $income = null; } elseif ($incomeOrExpenditure == 1) { - $expenditure = mt_rand(-1000, -500) * (1 + (mt_rand(-1, 1) / 4)); - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $expenditure = rand(-500, -1000) * (1 + rand(-0.25, +0.25)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } else { $expenditure = null; - $income = mt_rand(500, 1000) * (1 + (mt_rand(-1, 1) / 4)); + $income = rand(500, 1000) * (1 + rand(-0.25, +0.25)); } $dataArray = [$year, $period, @@ -96,19 +92,17 @@ $spreadsheet->getActiveSheet()->getStyle('A1:F1')->getAlignment()->setWrapText(true); $spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(12.5); $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(10.5); -$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD); -$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_INTEGER); +$spreadsheet->getActiveSheet()->getStyle('D2:D' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD2); +$spreadsheet->getActiveSheet()->getStyle('E2:F' . $row)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD_SIMPLE); $spreadsheet->getActiveSheet()->getColumnDimension('F')->setWidth(14); $spreadsheet->getActiveSheet()->freezePane('A2'); -$helper->displayGrid($spreadsheet->getActiveSheet()->toArray(null, false, true, true)); - // Set autofilter range -$filterRange = $spreadsheet->getActiveSheet()->calculateWorksheetDimension(); -$helper->log("Set autofilter for cells {$filterRange}"); -// Always include the complete filter range if you can! -// Excel does support setting only the caption row, but that's not a best practise... -$spreadsheet->getActiveSheet()->setAutoFilter($filterRange); +$helper->log('Set autofilter range'); +// Always include the complete filter range! +// Excel does support setting only the caption +// row, but that's not a best practise... +$spreadsheet->getActiveSheet()->setAutoFilter($spreadsheet->getActiveSheet()->calculateWorksheetDimension()); // Set active filters $autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter(); @@ -118,24 +112,22 @@ $autoFilter->getColumn('C') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'u*') + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + 'u*' + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); - -$helper->log('Set country code filter (Column C) to countries beginning with "U" ("United States" and "UK")'); - $autoFilter->getColumn('C') ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'japan') + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + 'japan' + ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); - -$helper->log('Add "Japan" to the country code filter (Column C)'); - -// Filter the Date column on a filter value of the last day of every period of the current year +// Filter the Date column on a filter value of the first day of every period of the current year // We us a dateGroup ruletype for this, although it is still a standard filter foreach ($periods as $period) { - $dateString = sprintf('%04d-%02d-01T00:00:00', $currentYear, $period); - $dateTime = new DateTime($dateString); - $endDate = (int) $dateTime->format('t'); + $endDate = date('t', mktime(0, 0, 0, $period, 1, $currentYear)); $autoFilter->getColumn('D') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER) @@ -150,20 +142,18 @@ ) ->setRuleType(Rule::AUTOFILTER_RULETYPE_DATEGROUP); } - -$helper->log('Add filter on the Date (Column D) to display only rows for the last day of each month'); - // Display only sales values that are blank // Standard filter, operator equals, and value of NULL $autoFilter->getColumn('E') ->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER) ->createRule() - ->setRule(Rule::AUTOFILTER_COLUMN_RULE_EQUAL, ''); - -$helper->log('Add filter on Sales Values (Column E) to display only blank values'); + ->setRule( + Rule::AUTOFILTER_COLUMN_RULE_EQUAL, + '' + ); // Execute filtering -$helper->log('Execute filtering (apply the filter rules)'); +$helper->log('Execute filtering'); $autoFilter->showHideRows(); // Set active sheet index to the first sheet, so Excel opens this as the first sheet @@ -171,5 +161,10 @@ // Display Results of filtering $helper->log('Display filtered rows'); - -$helper->displayGrid($spreadsheet->getActiveSheet()->toArray(null, false, true, true, true)); +foreach ($spreadsheet->getActiveSheet()->getRowIterator() as $row) { + if ($spreadsheet->getActiveSheet()->getRowDimension($row->getRowIndex())->getVisible()) { + $helper->log(' Row number - ' . $row->getRowIndex()); + $helper->log($spreadsheet->getActiveSheet()->getCell('C' . $row->getRowIndex())->getValue()); + $helper->log($spreadsheet->getActiveSheet()->getCell('D' . $row->getRowIndex())->getFormattedValue()); + } +} diff --git a/samples/Basic/01_Simple.php b/samples/Basic/01_Simple.php index c61c1d660c..89aca6d056 100644 --- a/samples/Basic/01_Simple.php +++ b/samples/Basic/01_Simple.php @@ -3,7 +3,8 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + +$spreadsheet = new Spreadsheet(); $helper->log('Create new Spreadsheet object'); $spreadsheet = new Spreadsheet(); @@ -61,4 +62,4 @@ ->setTitle('Simple'); // Save -$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Ods']); +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic/01_Simple_download_ods.php b/samples/Basic/01_Simple_download_ods.php index 98b5ca1966..0c38a0048c 100644 --- a/samples/Basic/01_Simple_download_ods.php +++ b/samples/Basic/01_Simple_download_ods.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; -require_once __DIR__ . '/../Bootstrap.php'; +require_once __DIR__ . '/../../src/Bootstrap.php'; $helper = new Sample(); if ($helper->isCli()) { diff --git a/samples/Basic/01_Simple_download_pdf.php b/samples/Basic/01_Simple_download_pdf.php index 424bc2cab4..5f3e71d785 100644 --- a/samples/Basic/01_Simple_download_pdf.php +++ b/samples/Basic/01_Simple_download_pdf.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; -require_once __DIR__ . '/../Bootstrap.php'; +require_once __DIR__ . '/../../src/Bootstrap.php'; $helper = new Sample(); if ($helper->isCli()) { @@ -44,7 +44,7 @@ // Set active sheet index to the first sheet, so Excel opens this as the first sheet $spreadsheet->setActiveSheetIndex(0); -IOFactory::registerWriter('Pdf', PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); +IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); // Redirect output to a client’s web browser (PDF) header('Content-Type: application/pdf'); diff --git a/samples/Basic/01_Simple_download_xls.php b/samples/Basic/01_Simple_download_xls.php index a7df25c486..46d1202221 100644 --- a/samples/Basic/01_Simple_download_xls.php +++ b/samples/Basic/01_Simple_download_xls.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; -require_once __DIR__ . '/../Bootstrap.php'; +require_once __DIR__ . '/../../src/Bootstrap.php'; $helper = new Sample(); if ($helper->isCli()) { diff --git a/samples/Basic/01_Simple_download_xlsx.php b/samples/Basic/01_Simple_download_xlsx.php index c67a17d065..93efe73df1 100644 --- a/samples/Basic/01_Simple_download_xlsx.php +++ b/samples/Basic/01_Simple_download_xlsx.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; -require_once __DIR__ . '/../Bootstrap.php'; +require_once __DIR__ . '/../../src/Bootstrap.php'; $helper = new Sample(); if ($helper->isCli()) { diff --git a/samples/Basic/02_Types.php b/samples/Basic/02_Types.php index caf6d7a1cc..79f109f510 100644 --- a/samples/Basic/02_Types.php +++ b/samples/Basic/02_Types.php @@ -1,6 +1,5 @@ log('Create new Spreadsheet object'); @@ -82,7 +80,7 @@ $spreadsheet->getActiveSheet() ->getStyle('C9') ->getNumberFormat() - ->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD); + ->setFormatCode(NumberFormat::FORMAT_DATE_YYYYMMDD2); $spreadsheet->getActiveSheet() ->setCellValue('A10', 'Date/Time') @@ -110,9 +108,9 @@ $richText->createText('你好 '); $payable = $richText->createTextRun('ä½  好 å—?'); -$payable->getFontOrThrow()->setBold(true); -$payable->getFontOrThrow()->setItalic(true); -$payable->getFontOrThrow()->setColor(new Color(Color::COLOR_DARKGREEN)); +$payable->getFont()->setBold(true); +$payable->getFont()->setItalic(true); +$payable->getFont()->setColor(new Color(Color::COLOR_DARKGREEN)); $richText->createText(', unless specified otherwise on the invoice.'); @@ -124,7 +122,7 @@ $richText2->createText("black text\n"); $red = $richText2->createTextRun('red text'); -$red->getFontOrThrow()->setColor(new Color(Color::COLOR_RED)); +$red->getFont()->setColor(new Color(Color::COLOR_RED)); $spreadsheet->getActiveSheet() ->getCell('C14') @@ -142,16 +140,9 @@ ->getHyperlink() ->setUrl('https://github.com/PHPOffice/PhpSpreadsheet') ->setTooltip('Navigate to PhpSpreadsheet website'); -$spreadsheet->getActiveSheet()->getStyle('C17')->getFont()->setHyperlinkTheme(); $spreadsheet->getActiveSheet() ->setCellValue('C18', '=HYPERLINK("mailto:abc@def.com","abc@def.com")'); -$spreadsheet->getActiveSheet()->getStyle('C18')->getFont()->setHyperlinkTheme(); - -$spreadsheet->getActiveSheet() - ->setCellValue('A20', 'String') - ->setCellValue('B20', 'inline') - ->setCellValueExplicit('C20', 'This will not be added to sharedStrings.xml', DataType::TYPE_INLINE); $spreadsheet->getActiveSheet() ->getColumnDimension('B') diff --git a/samples/Basic/03_Formulas.php b/samples/Basic/03_Formulas.php index 4d8aaf4d4a..e45382310b 100644 --- a/samples/Basic/03_Formulas.php +++ b/samples/Basic/03_Formulas.php @@ -3,7 +3,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -29,38 +28,38 @@ ->setCellValue('B3', 7) ->setCellValue('B4', 13) ->setCellValue('B5', '=SUM(B2:B4)'); -$helper->log('Sum of Range #1 is ' . $spreadsheet->getActiveSheet()->getCell('B5')->getCalculatedValueString()); +$helper->log('Sum of Range #1 is ' . $spreadsheet->getActiveSheet()->getCell('B5')->getCalculatedValue()); $spreadsheet->getActiveSheet()->setCellValue('C1', 'Range #2') ->setCellValue('C2', 5) ->setCellValue('C3', 11) ->setCellValue('C4', 17) ->setCellValue('C5', '=SUM(C2:C4)'); -$helper->log('Sum of Range #2 is ' . $spreadsheet->getActiveSheet()->getCell('C5')->getCalculatedValueString()); +$helper->log('Sum of Range #2 is ' . $spreadsheet->getActiveSheet()->getCell('C5')->getCalculatedValue()); $spreadsheet->getActiveSheet() ->setCellValue('A7', 'Total of both ranges:'); $spreadsheet->getActiveSheet() ->setCellValue('B7', '=SUM(B5:C5)'); -$helper->log('Sum of both Ranges is ' . $spreadsheet->getActiveSheet()->getCell('B7')->getCalculatedValueString()); +$helper->log('Sum of both Ranges is ' . $spreadsheet->getActiveSheet()->getCell('B7')->getCalculatedValue()); $spreadsheet->getActiveSheet() ->setCellValue('A8', 'Minimum of both ranges:'); $spreadsheet->getActiveSheet() ->setCellValue('B8', '=MIN(B2:C4)'); -$helper->log('Minimum value in either Range is ' . $spreadsheet->getActiveSheet()->getCell('B8')->getCalculatedValueString()); +$helper->log('Minimum value in either Range is ' . $spreadsheet->getActiveSheet()->getCell('B8')->getCalculatedValue()); $spreadsheet->getActiveSheet() ->setCellValue('A9', 'Maximum of both ranges:'); $spreadsheet->getActiveSheet() ->setCellValue('B9', '=MAX(B2:C4)'); -$helper->log('Maximum value in either Range is ' . $spreadsheet->getActiveSheet()->getCell('B9')->getCalculatedValueString()); +$helper->log('Maximum value in either Range is ' . $spreadsheet->getActiveSheet()->getCell('B9')->getCalculatedValue()); $spreadsheet->getActiveSheet() ->setCellValue('A10', 'Average of both ranges:'); $spreadsheet->getActiveSheet() ->setCellValue('B10', '=AVERAGE(B2:C4)'); -$helper->log('Average value of both Ranges is ' . $spreadsheet->getActiveSheet()->getCell('B10')->getCalculatedValueString()); +$helper->log('Average value of both Ranges is ' . $spreadsheet->getActiveSheet()->getCell('B10')->getCalculatedValue()); $spreadsheet->getActiveSheet() ->getColumnDimension('A') ->setAutoSize(true); diff --git a/samples/Basic/04_Printing.php b/samples/Basic/04_Printing.php index 936e01a01b..5e90fc9192 100644 --- a/samples/Basic/04_Printing.php +++ b/samples/Basic/04_Printing.php @@ -6,7 +6,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic/05_Feature_demo.php b/samples/Basic/05_Feature_demo.php index 7557df1e51..a85ebbc27f 100644 --- a/samples/Basic/05_Feature_demo.php +++ b/samples/Basic/05_Feature_demo.php @@ -1,9 +1,7 @@ write($spreadsheet, __FILE__); diff --git a/samples/Basic/05_UnexpectedCharacters.php b/samples/Basic/05_UnexpectedCharacters.php deleted file mode 100644 index 1766c6fccf..0000000000 --- a/samples/Basic/05_UnexpectedCharacters.php +++ /dev/null @@ -1,9 +0,0 @@ -write($spreadsheet, __FILE__); diff --git a/samples/Basic/06_Largescale.php b/samples/Basic/06_Largescale.php index 4dc8d4d196..2e8a3e67ed 100644 --- a/samples/Basic/06_Largescale.php +++ b/samples/Basic/06_Largescale.php @@ -1,9 +1,8 @@ write($spreadsheet, __FILE__); diff --git a/samples/Basic/07_Reader.php b/samples/Basic/07_Reader.php index c0fa4b2d7d..4d9bd79e2f 100644 --- a/samples/Basic/07_Reader.php +++ b/samples/Basic/07_Reader.php @@ -6,9 +6,7 @@ require __DIR__ . '/../Header.php'; // Create temporary file that will be read -/** @var PhpOffice\PhpSpreadsheet\Spreadsheet */ $sampleSpreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ $filename = $helper->getTemporaryFilename(); $writer = new Xlsx($sampleSpreadsheet); $writer->save($filename); @@ -19,4 +17,3 @@ // Save $helper->write($spreadsheet, __FILE__); -unlink($filename); diff --git a/samples/Basic/08_Conditional_formatting.php b/samples/Basic/08_Conditional_formatting.php index 8bb6cc0861..2f54863214 100644 --- a/samples/Basic/08_Conditional_formatting.php +++ b/samples/Basic/08_Conditional_formatting.php @@ -7,7 +7,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -61,7 +60,7 @@ ->addCondition('400'); $conditional1->getStyle()->getFont()->getColor()->setARGB(Color::COLOR_YELLOW); $conditional1->getStyle()->getFont()->setBold(true); -$conditional1->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_INTEGER); +$conditional1->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); $conditional2 = new Conditional(); $conditional2->setConditionType(Conditional::CONDITION_CELLIS) @@ -69,7 +68,7 @@ ->addCondition('0'); $conditional2->getStyle()->getFont()->getColor()->setARGB(Color::COLOR_RED); $conditional2->getStyle()->getFont()->setItalic(true); -$conditional2->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_INTEGER); +$conditional2->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); $conditional3 = new Conditional(); $conditional3->setConditionType(Conditional::CONDITION_CELLIS) @@ -77,7 +76,7 @@ ->addCondition('0'); $conditional3->getStyle()->getFont()->getColor()->setARGB(Color::COLOR_GREEN); $conditional3->getStyle()->getFont()->setItalic(true); -$conditional3->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_INTEGER); +$conditional3->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); $conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('B2')->getConditionalStyles(); $conditionalStyles[] = $conditional1; diff --git a/samples/Basic/08_Conditional_formatting_2.php b/samples/Basic/08_Conditional_formatting_2.php index 40b5e47c63..818cdd9f01 100644 --- a/samples/Basic/08_Conditional_formatting_2.php +++ b/samples/Basic/08_Conditional_formatting_2.php @@ -6,7 +6,6 @@ use PhpOffice\PhpSpreadsheet\Style\NumberFormat; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic/09_Pagebreaks.php b/samples/Basic/09_Pagebreaks.php index 7b81c77727..ab99a0790d 100644 --- a/samples/Basic/09_Pagebreaks.php +++ b/samples/Basic/09_Pagebreaks.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic1/11_Documentsecurity.php b/samples/Basic/11_Documentsecurity.php similarity index 80% rename from samples/Basic1/11_Documentsecurity.php rename to samples/Basic/11_Documentsecurity.php index 567445a75d..ec537ab3f7 100644 --- a/samples/Basic1/11_Documentsecurity.php +++ b/samples/Basic/11_Documentsecurity.php @@ -3,7 +3,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -40,13 +39,10 @@ // Set sheet security $helper->log('Set sheet security'); $spreadsheet->getActiveSheet()->getProtection()->setPassword('PhpSpreadsheet'); -// setSheet should be true in order to enable protection! -$spreadsheet->getActiveSheet()->getProtection()->setSheet(true); -// The following are set to false, i.e. user is allowed to -// sort, insert rows, or format cells without unprotecting sheet. -$spreadsheet->getActiveSheet()->getProtection()->setSort(false); -$spreadsheet->getActiveSheet()->getProtection()->setInsertRows(false); -$spreadsheet->getActiveSheet()->getProtection()->setFormatCells(false); +$spreadsheet->getActiveSheet()->getProtection()->setSheet(true); // This should be enabled in order to enable any of the following! +$spreadsheet->getActiveSheet()->getProtection()->setSort(true); +$spreadsheet->getActiveSheet()->getProtection()->setInsertRows(true); +$spreadsheet->getActiveSheet()->getProtection()->setFormatCells(true); // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic1/12_CellProtection.php b/samples/Basic/12_CellProtection.php similarity index 96% rename from samples/Basic1/12_CellProtection.php rename to samples/Basic/12_CellProtection.php index b30f7b0c98..8a1b2a0b60 100644 --- a/samples/Basic1/12_CellProtection.php +++ b/samples/Basic/12_CellProtection.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Style\Protection; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic1/13_Calculation.php b/samples/Basic/13_Calculation.php similarity index 96% rename from samples/Basic1/13_Calculation.php rename to samples/Basic/13_Calculation.php index 3fcf808c66..087b443fe5 100644 --- a/samples/Basic1/13_Calculation.php +++ b/samples/Basic/13_Calculation.php @@ -6,7 +6,6 @@ mt_srand(1234567890); require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // List functions $helper->log('List implemented functions'); @@ -158,12 +157,9 @@ $helper->log('Calculated data'); for ($col = 'B'; $col != 'G'; ++$col) { for ($row = 14; $row <= 41; ++$row) { - $formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue(); - if ( - is_string($formula) - && ($formula[0] == '=') - ) { - $helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValueString()); + if ((($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) && + ($formula[0] == '=')) { + $helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue()); } } } diff --git a/samples/Basic/13_CalculationCyclicFormulae.php b/samples/Basic/13_CalculationCyclicFormulae.php new file mode 100644 index 0000000000..26e9784db4 --- /dev/null +++ b/samples/Basic/13_CalculationCyclicFormulae.php @@ -0,0 +1,33 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); + +// Add some data, we will use some formulas here +$helper->log('Add some data and formulas'); +$spreadsheet->getActiveSheet()->setCellValue('A1', '=B1') + ->setCellValue('A2', '=B2+1') + ->setCellValue('B1', '=A1+1') + ->setCellValue('B2', '=A2'); + +Calculation::getInstance($spreadsheet)->cyclicFormulaCount = 100; + +// Calculated data +$helper->log('Calculated data'); +for ($row = 1; $row <= 2; ++$row) { + for ($col = 'A'; $col != 'C'; ++$col) { + if ((($formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue()) !== null) && + ($formula[0] == '=')) { + $helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValue()); + } + } +} + +// Save +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic1/14_Xls.php b/samples/Basic/14_Xls.php similarity index 77% rename from samples/Basic1/14_Xls.php rename to samples/Basic/14_Xls.php index 3750f3c368..ce27eb8cd0 100644 --- a/samples/Basic1/14_Xls.php +++ b/samples/Basic/14_Xls.php @@ -3,10 +3,8 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Spreadsheet */ $spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ $filename = $helper->getFilename(__FILE__, 'xls'); $writer = IOFactory::createWriter($spreadsheet, 'Xls'); diff --git a/samples/Basic1/15_Datavalidation.php b/samples/Basic/15_Datavalidation.php similarity index 96% rename from samples/Basic1/15_Datavalidation.php rename to samples/Basic/15_Datavalidation.php index 619d03235b..fb76b4dc2d 100644 --- a/samples/Basic1/15_Datavalidation.php +++ b/samples/Basic/15_Datavalidation.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -48,8 +47,8 @@ $validation->setError('Only numbers between 10 and 20 are allowed!'); $validation->setPromptTitle('Allowed input'); $validation->setPrompt('Only numbers between 10 and 20 are allowed.'); -$validation->setFormula1('10'); -$validation->setFormula2('20'); +$validation->setFormula1(10); +$validation->setFormula2(20); $validation = $spreadsheet->getActiveSheet()->getCell('B5')->getDataValidation(); $validation->setType(DataValidation::TYPE_LIST); diff --git a/samples/Basic/16_Csv.php b/samples/Basic/16_Csv.php new file mode 100644 index 0000000000..ceb8b2f5c2 --- /dev/null +++ b/samples/Basic/16_Csv.php @@ -0,0 +1,38 @@ +log('Write to CSV format'); +$writer = IOFactory::createWriter($spreadsheet, 'Csv')->setDelimiter(',') + ->setEnclosure('"') + ->setSheetIndex(0); + +$callStartTime = microtime(true); +$filename = $helper->getTemporaryFilename('csv'); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); + +$helper->log('Read from CSV format'); + +$reader = IOFactory::createReader('Csv')->setDelimiter(',') + ->setEnclosure('"') + ->setSheetIndex(0); + +$callStartTime = microtime(true); +$spreadsheetFromCSV = $reader->load($filename); +$helper->logRead('Csv', $filename, $callStartTime); + +// Write Xlsx +$helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']); + +// Write CSV +$filenameCSV = $helper->getFilename(__FILE__, 'csv'); +$writerCSV = IOFactory::createWriter($spreadsheetFromCSV, 'Csv'); +$writerCSV->setExcelCompatibility(true); + +$callStartTime = microtime(true); +$writerCSV->save($filenameCSV); +$helper->logWrite($writerCSV, $filenameCSV, $callStartTime); diff --git a/samples/Basic/17_Html.php b/samples/Basic/17_Html.php new file mode 100644 index 0000000000..b90b7212d0 --- /dev/null +++ b/samples/Basic/17_Html.php @@ -0,0 +1,13 @@ +getFilename(__FILE__, 'html'); +$writer = IOFactory::createWriter($spreadsheet, 'Html'); + +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Basic1/18_Extendedcalculation.php b/samples/Basic/18_Extendedcalculation.php similarity index 95% rename from samples/Basic1/18_Extendedcalculation.php rename to samples/Basic/18_Extendedcalculation.php index 5acc1a5942..c1ec2c0a43 100644 --- a/samples/Basic1/18_Extendedcalculation.php +++ b/samples/Basic/18_Extendedcalculation.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // List functions $helper->log('List implemented functions'); @@ -65,6 +64,6 @@ // Calculated data $helper->log('Calculated data'); -$helper->log('Value of B14 [=COUNT(B2:B12)]: ' . $spreadsheet->getActiveSheet()->getCell('B14')->getCalculatedValueString()); +$helper->log('Value of B14 [=COUNT(B2:B12)]: ' . $spreadsheet->getActiveSheet()->getCell('B14')->getCalculatedValue()); $helper->logEndingNotes(); diff --git a/samples/Basic1/19_Namedrange.php b/samples/Basic/19_Namedrange.php similarity index 85% rename from samples/Basic1/19_Namedrange.php rename to samples/Basic/19_Namedrange.php index e4b79f995f..d89e1b04d9 100644 --- a/samples/Basic1/19_Namedrange.php +++ b/samples/Basic/19_Namedrange.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -32,14 +31,11 @@ // Define named ranges $helper->log('Define named ranges'); -$spreadsheet->addNamedRange(new NamedRange('PersonName', $spreadsheet->getActiveSheet(), '$B$1')); -$spreadsheet->addNamedRange(new NamedRange('PersonLN', $spreadsheet->getActiveSheet(), '$B$2')); +$spreadsheet->addNamedRange(new NamedRange('PersonName', $spreadsheet->getActiveSheet(), 'B1')); +$spreadsheet->addNamedRange(new NamedRange('PersonLN', $spreadsheet->getActiveSheet(), 'B2')); // Rename named ranges $helper->log('Rename named ranges'); -if ($spreadsheet->getNamedRange('PersonName') === null) { - throw new Exception('named range not found'); -} $spreadsheet->getNamedRange('PersonName')->setName('PersonFN'); // Rename worksheet @@ -62,9 +58,9 @@ // Resolve range $helper->log('Resolve range'); -$helper->log('Cell B1 {=PersonFN}: ' . $spreadsheet->getActiveSheet()->getCell('B1')->getCalculatedValueString()); -$helper->log('Cell B3 {=PersonFN & " " & PersonLN}: ' . $spreadsheet->getActiveSheet()->getCell('B3')->getCalculatedValueString()); -$helper->log('Cell Person!B1: ' . $spreadsheet->getActiveSheet()->getCell('Person!B1')->getCalculatedValueString()); +$helper->log('Cell B1 {=PersonFN}: ' . $spreadsheet->getActiveSheet()->getCell('B1')->getCalculatedValue()); +$helper->log('Cell B3 {=PersonFN & " " & PersonLN}: ' . $spreadsheet->getActiveSheet()->getCell('B3')->getCalculatedValue()); +$helper->log('Cell Person!B1: ' . $spreadsheet->getActiveSheet()->getCell('Person!B1')->getCalculatedValue()); // Rename worksheet $helper->log('Rename worksheet'); diff --git a/samples/Basic/20_Read_Excel2003XML.php b/samples/Basic/20_Read_Excel2003XML.php new file mode 100644 index 0000000000..44425e20a5 --- /dev/null +++ b/samples/Basic/20_Read_Excel2003XML.php @@ -0,0 +1,13 @@ +logRead('Xml', $filename, $callStartTime); + +// Save +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/20_Read_Gnumeric.php b/samples/Basic/20_Read_Gnumeric.php similarity index 84% rename from samples/Basic2/20_Read_Gnumeric.php rename to samples/Basic/20_Read_Gnumeric.php index 76b5e30254..2d6ce2215a 100644 --- a/samples/Basic2/20_Read_Gnumeric.php +++ b/samples/Basic/20_Read_Gnumeric.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $filename = __DIR__ . '/../templates/GnumericTest.gnumeric'; $callStartTime = microtime(true); $spreadsheet = IOFactory::load($filename); diff --git a/samples/Basic2/20_Read_Ods.php b/samples/Basic/20_Read_Ods.php similarity index 84% rename from samples/Basic2/20_Read_Ods.php rename to samples/Basic/20_Read_Ods.php index e9ec14f36f..64f54827b8 100644 --- a/samples/Basic2/20_Read_Ods.php +++ b/samples/Basic/20_Read_Ods.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $filename = __DIR__ . '/../templates/OOCalcTest.ods'; $callStartTime = microtime(true); $spreadsheet = IOFactory::load($filename); diff --git a/samples/Basic2/20_Read_Sylk.php b/samples/Basic/20_Read_Sylk.php similarity index 84% rename from samples/Basic2/20_Read_Sylk.php rename to samples/Basic/20_Read_Sylk.php index 12a3259191..1a0645938a 100644 --- a/samples/Basic2/20_Read_Sylk.php +++ b/samples/Basic/20_Read_Sylk.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $filename = __DIR__ . '/../templates/SylkTest.slk'; $callStartTime = microtime(true); $spreadsheet = IOFactory::load($filename); diff --git a/samples/Basic2/20_Read_Xls.php b/samples/Basic/20_Read_Xls.php similarity index 82% rename from samples/Basic2/20_Read_Xls.php rename to samples/Basic/20_Read_Xls.php index 23d488c348..9e5fa014ad 100644 --- a/samples/Basic2/20_Read_Xls.php +++ b/samples/Basic/20_Read_Xls.php @@ -3,11 +3,10 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Spreadsheet */ + $spreadsheet = require __DIR__ . '/../templates/sampleSpreadsheet.php'; // Write temporary file -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ $filename = $helper->getTemporaryFilename('xls'); $writer = IOFactory::createWriter($spreadsheet, 'Xls'); $callStartTime = microtime(true); @@ -18,7 +17,6 @@ $callStartTime = microtime(true); $spreadsheet = IOFactory::load($filename); $helper->logRead('Xls', $filename, $callStartTime); -unlink($filename); // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic/22_Heavily_formatted.php b/samples/Basic/22_Heavily_formatted.php new file mode 100644 index 0000000000..d7ba861bc8 --- /dev/null +++ b/samples/Basic/22_Heavily_formatted.php @@ -0,0 +1,48 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); + +// Set document properties +$helper->log('Set document properties'); +$spreadsheet->getProperties()->setCreator('Maarten Balliauw') + ->setLastModifiedBy('Maarten Balliauw') + ->setTitle('Office 2007 XLSX Test Document') + ->setSubject('Office 2007 XLSX Test Document') + ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') + ->setKeywords('office 2007 openxml php') + ->setCategory('Test result file'); + +// Add some data +$helper->log('Add some data'); +$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], + ], + ] +); + +$spreadsheet->getActiveSheet()->getStyle('C5:R95')->applyFromArray( + ['fill' => [ + 'fillType' => Fill::FILL_SOLID, + 'color' => ['argb' => 'FFFFFF00'], + ], + ] +); + +// Save +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic/23_Sharedstyles.php b/samples/Basic/23_Sharedstyles.php new file mode 100644 index 0000000000..b5398883fb --- /dev/null +++ b/samples/Basic/23_Sharedstyles.php @@ -0,0 +1,59 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); + +// Set document properties +$helper->log('Set document properties'); +$spreadsheet->getProperties()->setCreator('Maarten Balliauw') + ->setLastModifiedBy('Maarten Balliauw') + ->setTitle('Office 2007 XLSX Test Document') + ->setSubject('Office 2007 XLSX Test Document') + ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') + ->setKeywords('office 2007 openxml php') + ->setCategory('Test result file'); + +// Add some data +$helper->log('Add some data'); +$spreadsheet->setActiveSheetIndex(0); + +$sharedStyle1 = new Style(); +$sharedStyle2 = new Style(); + +$sharedStyle1->applyFromArray( + ['fill' => [ + '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], + ], + ] +); + +$spreadsheet->getActiveSheet()->duplicateStyle($sharedStyle1, 'A1:T100'); +$spreadsheet->getActiveSheet()->duplicateStyle($sharedStyle2, 'C5:R95'); + +// Save +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/24_Readfilter.php b/samples/Basic/24_Readfilter.php similarity index 80% rename from samples/Basic2/24_Readfilter.php rename to samples/Basic/24_Readfilter.php index f0e29ad8b7..844996f249 100644 --- a/samples/Basic2/24_Readfilter.php +++ b/samples/Basic/24_Readfilter.php @@ -3,16 +3,13 @@ namespace PhpOffice\PhpSpreadsheet; use PhpOffice\PhpSpreadsheet\Reader\IReadFilter; -use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; require __DIR__ . '/../Header.php'; // Write temporary file -/** @var Spreadsheet */ $largeSpreadsheet = require __DIR__ . '/../templates/largeSpreadsheet.php'; $writer = new Xlsx($largeSpreadsheet); -/** @var Helper\Sample $helper */ $filename = $helper->getTemporaryFilename(); $callStartTime = microtime(true); $writer->save($filename); @@ -20,7 +17,7 @@ class MyReadFilter implements IReadFilter { - public function readCell(string $columnAddress, int $row, string $worksheetName = ''): bool + public function readCell($column, $row, $worksheetName = '') { // Read title row and rows 20 - 30 if ($row == 1 || ($row >= 20 && $row <= 30)) { @@ -32,11 +29,10 @@ public function readCell(string $columnAddress, int $row, string $worksheetName } $helper->log('Load from Xlsx file'); -$reader = new XlsxReader(); +$reader = IOFactory::createReader('Xlsx'); $reader->setReadFilter(new MyReadFilter()); $callStartTime = microtime(true); $spreadsheet = $reader->load($filename); -unlink($filename); $helper->logRead('Xlsx', $filename, $callStartTime); $helper->log('Remove unnecessary rows'); $spreadsheet->getActiveSheet()->removeRow(2, 18); diff --git a/samples/Basic/25_In_memory_image.php b/samples/Basic/25_In_memory_image.php new file mode 100644 index 0000000000..a897486dfd --- /dev/null +++ b/samples/Basic/25_In_memory_image.php @@ -0,0 +1,40 @@ +log('Create new Spreadsheet object'); +$spreadsheet = new Spreadsheet(); + +// Set document properties +$helper->log('Set document properties'); +$spreadsheet->getProperties()->setCreator('Maarten Balliauw') + ->setLastModifiedBy('Maarten Balliauw') + ->setTitle('Office 2007 XLSX Test Document') + ->setSubject('Office 2007 XLSX Test Document') + ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') + ->setKeywords('office 2007 openxml php') + ->setCategory('Test result file'); + +// Generate an image +$helper->log('Generate an image'); +$gdImage = @imagecreatetruecolor(120, 20) or die('Cannot Initialize new GD image stream'); +$textColor = imagecolorallocate($gdImage, 255, 255, 255); +imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor); + +// Add a drawing to the worksheet +$helper->log('Add a drawing to the worksheet'); +$drawing = new MemoryDrawing(); +$drawing->setName('Sample image'); +$drawing->setDescription('Sample image'); +$drawing->setImageResource($gdImage); +$drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); +$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); +$drawing->setHeight(36); +$drawing->setWorksheet($spreadsheet->getActiveSheet()); + +// Save +$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html']); diff --git a/samples/Basic/26_Utf8.php b/samples/Basic/26_Utf8.php new file mode 100644 index 0000000000..af048246d3 --- /dev/null +++ b/samples/Basic/26_Utf8.php @@ -0,0 +1,39 @@ +log('Load Xlsx template file'); +$reader = IOFactory::createReader('Xlsx'); +$spreadsheet = $reader->load(__DIR__ . '/../templates/26template.xlsx'); + +// at this point, we could do some manipulations with the template, but we skip this step +$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']); + +// Export to PDF (.pdf) +$helper->log('Write to PDF format'); +IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf::class); +$helper->write($spreadsheet, __FILE__, ['Pdf']); + +// Remove first two rows with field headers before exporting to CSV +$helper->log('Removing first two heading rows for CSV export'); +$worksheet = $spreadsheet->getActiveSheet(); +$worksheet->removeRow(1, 2); + +// Export to CSV (.csv) +$helper->log('Write to CSV format'); +$writer = IOFactory::createWriter($spreadsheet, 'Csv'); +$filename = $helper->getFilename(__FILE__, 'csv'); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); + +// Export to CSV with BOM (.csv) +$filename = str_replace('.csv', '-bom.csv', $filename); +$helper->log('Write to CSV format (with BOM)'); +$writer->setUseBOM(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Basic/27_Images_Xls.php b/samples/Basic/27_Images_Xls.php new file mode 100644 index 0000000000..4c20a9ac8b --- /dev/null +++ b/samples/Basic/27_Images_Xls.php @@ -0,0 +1,13 @@ +log('Load Xlsx template file'); +$reader = IOFactory::createReader('Xls'); +$spreadsheet = $reader->load(__DIR__ . '/../templates/27template.xls'); + +// Save +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic/28_Iterator.php b/samples/Basic/28_Iterator.php new file mode 100644 index 0000000000..4aec7a9203 --- /dev/null +++ b/samples/Basic/28_Iterator.php @@ -0,0 +1,34 @@ +getTemporaryFilename(); +$writer = new Xlsx($sampleSpreadsheet); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); + +$callStartTime = microtime(true); +$reader = IOFactory::createReader('Xlsx'); +$spreadsheet = $reader->load($filename); +$helper->logRead('Xlsx', $filename, $callStartTime); +$helper->log('Iterate worksheets'); +foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { + $helper->log('Worksheet - ' . $worksheet->getTitle()); + + foreach ($worksheet->getRowIterator() as $row) { + $helper->log(' Row number - ' . $row->getRowIndex()); + + $cellIterator = $row->getCellIterator(); + $cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set + foreach ($cellIterator as $cell) { + if ($cell !== null) { + $helper->log(' Cell - ' . $cell->getCoordinate() . ' - ' . $cell->getCalculatedValue()); + } + } + } +} diff --git a/samples/Basic2/29_Advanced_value_binder.php b/samples/Basic/29_Advanced_value_binder.php similarity index 98% rename from samples/Basic2/29_Advanced_value_binder.php rename to samples/Basic/29_Advanced_value_binder.php index 07e9dccb09..74c16c21a4 100644 --- a/samples/Basic2/29_Advanced_value_binder.php +++ b/samples/Basic/29_Advanced_value_binder.php @@ -5,7 +5,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Set timezone $helper->log('Set timezone'); diff --git a/samples/Basic3/30_Template.php b/samples/Basic/30_Template.php similarity index 91% rename from samples/Basic3/30_Template.php rename to samples/Basic/30_Template.php index 246a44ab76..b70c18b610 100644 --- a/samples/Basic3/30_Template.php +++ b/samples/Basic/30_Template.php @@ -4,16 +4,16 @@ use PhpOffice\PhpSpreadsheet\Shared\Date; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $helper->log('Load from Xls template'); $reader = IOFactory::createReader('Xls'); $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, diff --git a/samples/Basic3/31_Document_properties_write.php b/samples/Basic/31_Document_properties_write.php similarity index 94% rename from samples/Basic3/31_Document_properties_write.php rename to samples/Basic/31_Document_properties_write.php index 20ba4860f1..dec3cc32a8 100644 --- a/samples/Basic3/31_Document_properties_write.php +++ b/samples/Basic/31_Document_properties_write.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $inputFileType = 'Xlsx'; $inputFileName = __DIR__ . '/../templates/31docproperties.xlsx'; @@ -56,7 +56,7 @@ $propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty); $propertyType = $spreadsheet->getProperties()->getCustomPropertyType($customProperty); if ($propertyType == Properties::PROPERTY_TYPE_DATE) { - $formattedValue = is_numeric($propertyValue) ? date('d-M-Y H:i:s', (int) $propertyValue) : '*****INVALID*****'; + $formattedValue = date('d-M-Y H:i:s', $propertyValue); } elseif ($propertyType == Properties::PROPERTY_TYPE_BOOLEAN) { $formattedValue = $propertyValue ? 'TRUE' : 'FALSE'; } else { diff --git a/samples/Basic3/31_Document_properties_write_xls.php b/samples/Basic/31_Document_properties_write_xls.php similarity index 94% rename from samples/Basic3/31_Document_properties_write_xls.php rename to samples/Basic/31_Document_properties_write_xls.php index 03ce3b400f..d58c318270 100644 --- a/samples/Basic3/31_Document_properties_write_xls.php +++ b/samples/Basic/31_Document_properties_write_xls.php @@ -4,7 +4,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $inputFileType = 'Xls'; $inputFileName = __DIR__ . '/../templates/31docproperties.xls'; @@ -56,7 +56,7 @@ $propertyValue = $spreadsheet->getProperties()->getCustomPropertyValue($customProperty); $propertyType = $spreadsheet->getProperties()->getCustomPropertyType($customProperty); if ($propertyType == Properties::PROPERTY_TYPE_DATE) { - $formattedValue = is_numeric($propertyValue) ? date('d-M-Y H:i:s', (int) $propertyValue) : '*****INVALID*****'; + $formattedValue = date('d-M-Y H:i:s', $propertyValue); } elseif ($propertyType == Properties::PROPERTY_TYPE_BOOLEAN) { $formattedValue = $propertyValue ? 'TRUE' : 'FALSE'; } else { diff --git a/samples/Basic3/37_Page_layout_view.php b/samples/Basic/37_Page_layout_view.php similarity index 94% rename from samples/Basic3/37_Page_layout_view.php rename to samples/Basic/37_Page_layout_view.php index e54ccf299b..d9bac80a87 100644 --- a/samples/Basic3/37_Page_layout_view.php +++ b/samples/Basic/37_Page_layout_view.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Worksheet\SheetView; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic3/38_Clone_worksheet.php b/samples/Basic/38_Clone_worksheet.php similarity index 96% rename from samples/Basic3/38_Clone_worksheet.php rename to samples/Basic/38_Clone_worksheet.php index ce17a03c8c..83f2d9ce53 100644 --- a/samples/Basic3/38_Clone_worksheet.php +++ b/samples/Basic/38_Clone_worksheet.php @@ -3,7 +3,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); diff --git a/samples/Basic3/39_Dropdown.php b/samples/Basic/39_Dropdown.php similarity index 86% rename from samples/Basic3/39_Dropdown.php rename to samples/Basic/39_Dropdown.php index 398d7e3620..e34d73e6ae 100644 --- a/samples/Basic3/39_Dropdown.php +++ b/samples/Basic/39_Dropdown.php @@ -5,7 +5,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -21,9 +20,7 @@ ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') ->setKeywords('Office PhpSpreadsheet php') ->setCategory('Test result file'); - -/** @return array */ -function transpose(string $value): array +function transpose($value) { return [$value]; } @@ -33,23 +30,23 @@ function transpose(string $value): array $column = 'F'; // Set data for dropdowns -$continents = glob(__DIR__ . '/data/continents/*') ?: []; +$continents = glob(__DIR__ . '/data/continents/*'); foreach ($continents as $key => $filename) { $continent = pathinfo($filename, PATHINFO_FILENAME); $helper->log("Loading $continent"); $continent = str_replace(' ', '_', $continent); - $countries = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []; + $countries = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $countryCount = count($countries); // Transpose $countries from a row to a column array - $countries = array_map(fn (mixed $value): array => [$value], $countries); + $countries = array_map('transpose', $countries); $spreadsheet->getActiveSheet() ->fromArray($countries, null, $column . '1'); $spreadsheet->addNamedRange( new NamedRange( $continent, $spreadsheet->getActiveSheet(), - '$' . $column . '$1:$' . $column . '$' . $countryCount + $column . '1:' . $column . $countryCount ) ); $spreadsheet->getActiveSheet() @@ -71,7 +68,7 @@ function transpose(string $value): array new NamedRange( 'Continents', $spreadsheet->getActiveSheet(), - '$' . $continentColumn . '$1:$' . $continentColumn . '$' . count($continents) + $continentColumn . '1:' . $continentColumn . count($continents) ) ); @@ -129,5 +126,4 @@ function transpose(string $value): array $spreadsheet->getActiveSheet()->getColumnDimension('B')->setWidth(30); // Save -$helper->log('Not writing to Xls - formulae with defined names not yet supported'); -$helper->write($spreadsheet, __FILE__, ['Xlsx']); +$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic4/40_Duplicate_style.php b/samples/Basic/40_Duplicate_style.php similarity index 87% rename from samples/Basic4/40_Duplicate_style.php rename to samples/Basic/40_Duplicate_style.php index deb365c2df..a2dc5f5f39 100644 --- a/samples/Basic4/40_Duplicate_style.php +++ b/samples/Basic/40_Duplicate_style.php @@ -5,7 +5,7 @@ use PhpOffice\PhpSpreadsheet\Style\Style; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $helper->log('Create new Spreadsheet object'); $spreadsheet = new Spreadsheet(); $worksheet = $spreadsheet->getActiveSheet(); @@ -30,7 +30,7 @@ } } $d = microtime(true) - $t; -$helper->log('Add data (end) . time: ' . (string) round($d, 2) . ' s'); +$helper->log('Add data (end) . time: ' . round($d . 2) . ' s'); // Save $helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic4/41_Password.php b/samples/Basic/41_Password.php similarity index 77% rename from samples/Basic4/41_Password.php rename to samples/Basic/41_Password.php index 7523aa21a3..9aa8e6db9c 100644 --- a/samples/Basic4/41_Password.php +++ b/samples/Basic/41_Password.php @@ -1,7 +1,6 @@ getSecurity()->setWorkbookPassword('secret'); // Save -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ $helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic4/42_RichText.php b/samples/Basic/42_RichText.php similarity index 95% rename from samples/Basic4/42_RichText.php rename to samples/Basic/42_RichText.php index 4bd8d35662..43b35a62c1 100644 --- a/samples/Basic4/42_RichText.php +++ b/samples/Basic/42_RichText.php @@ -4,7 +4,6 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Create new Spreadsheet object $helper->log('Create new Spreadsheet object'); @@ -31,7 +30,7 @@ while this block uses an underline.

-

+

I want to eat healthy food pizza. '; diff --git a/samples/Basic4/43_Merge_workbooks.php b/samples/Basic/43_Merge_workbooks.php similarity index 88% rename from samples/Basic4/43_Merge_workbooks.php rename to samples/Basic/43_Merge_workbooks.php index 80a2cd336e..86314b3ba3 100644 --- a/samples/Basic4/43_Merge_workbooks.php +++ b/samples/Basic/43_Merge_workbooks.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $helper->log('Load MergeBook1 from Xlsx file'); $filename1 = __DIR__ . '/../templates/43mergeBook1.xlsx'; $callStartTime = microtime(true); @@ -18,10 +18,6 @@ foreach ($spreadsheet2->getSheetNames() as $sheetName) { $sheet = $spreadsheet2->getSheetByName($sheetName); - if ($sheet === null) { - continue; - } - $sheet->setTitle($sheet->getTitle() . ' copied'); $spreadsheet1->addExternalSheet($sheet); } diff --git a/samples/Basic/44_Worksheet_info.php b/samples/Basic/44_Worksheet_info.php new file mode 100644 index 0000000000..33c0cd0577 --- /dev/null +++ b/samples/Basic/44_Worksheet_info.php @@ -0,0 +1,26 @@ +getTemporaryFilename(); +$writer = new Xlsx($sampleSpreadsheet); +$writer->save($filename); + +$inputFileType = IOFactory::identify($filename); +$reader = IOFactory::createReader($inputFileType); +$sheetList = $reader->listWorksheetNames($filename); +$sheetInfo = $reader->listWorksheetInfo($filename); + +$helper->log('File Type:'); +var_dump($inputFileType); + +$helper->log('Worksheet Names:'); +var_dump($sheetList); + +$helper->log('Worksheet Names:'); +var_dump($sheetInfo); diff --git a/samples/Basic/45_Quadratic_equation_solver.php b/samples/Basic/45_Quadratic_equation_solver.php new file mode 100644 index 0000000000..a59a0cebf9 --- /dev/null +++ b/samples/Basic/45_Quadratic_equation_solver.php @@ -0,0 +1,43 @@ + +

+ Enter the coefficients for the Ax2 + Bx + C = 0 + + + + + + + + + + +
+
+ If A=0, the equation is not quadratic. + + +log('The equation is not quadratic'); + } else { + // Calculate and Display the results + $helper->log('
Roots:
'); + + $discriminantFormula = '=POWER(' . $_POST['B'] . ',2) - (4 * ' . $_POST['A'] . ' * ' . $_POST['C'] . ')'; + $discriminant = Calculation::getInstance()->calculateFormula($discriminantFormula); + + $r1Formula = '=IMDIV(IMSUM(-' . $_POST['B'] . ',IMSQRT(' . $discriminant . ')),2 * ' . $_POST['A'] . ')'; + $r2Formula = '=IF(' . $discriminant . '=0,"Only one root",IMDIV(IMSUB(-' . $_POST['B'] . ',IMSQRT(' . $discriminant . ')),2 * ' . $_POST['A'] . '))'; + + $helper->log(Calculation::getInstance()->calculateFormula($r1Formula)); + $helper->log(Calculation::getInstance()->calculateFormula($r2Formula)); + $callEndTime = microtime(true); + $helper->logEndingNotes(); + } +} diff --git a/samples/Basic4/46_ReadHtml.php b/samples/Basic/46_ReadHtml.php similarity index 87% rename from samples/Basic4/46_ReadHtml.php rename to samples/Basic/46_ReadHtml.php index 796733ecca..bd37af9b2a 100644 --- a/samples/Basic4/46_ReadHtml.php +++ b/samples/Basic/46_ReadHtml.php @@ -6,7 +6,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $html = __DIR__ . '/../templates/46readHtml.html'; $callStartTime = microtime(true); diff --git a/samples/Basic3/data/continents/Africa.txt b/samples/Basic/data/continents/Africa.txt similarity index 100% rename from samples/Basic3/data/continents/Africa.txt rename to samples/Basic/data/continents/Africa.txt diff --git a/samples/Basic3/data/continents/Asia.txt b/samples/Basic/data/continents/Asia.txt similarity index 100% rename from samples/Basic3/data/continents/Asia.txt rename to samples/Basic/data/continents/Asia.txt diff --git a/samples/Basic3/data/continents/Europe.txt b/samples/Basic/data/continents/Europe.txt similarity index 100% rename from samples/Basic3/data/continents/Europe.txt rename to samples/Basic/data/continents/Europe.txt diff --git a/samples/Basic3/data/continents/North America.txt b/samples/Basic/data/continents/North America.txt similarity index 100% rename from samples/Basic3/data/continents/North America.txt rename to samples/Basic/data/continents/North America.txt diff --git a/samples/Basic3/data/continents/Oceania.txt b/samples/Basic/data/continents/Oceania.txt similarity index 100% rename from samples/Basic3/data/continents/Oceania.txt rename to samples/Basic/data/continents/Oceania.txt diff --git a/samples/Basic3/data/continents/South America.txt b/samples/Basic/data/continents/South America.txt similarity index 100% rename from samples/Basic3/data/continents/South America.txt rename to samples/Basic/data/continents/South America.txt diff --git a/samples/Basic1/13_CalculationCyclicFormulae.php b/samples/Basic1/13_CalculationCyclicFormulae.php deleted file mode 100644 index 5f0fc3632d..0000000000 --- a/samples/Basic1/13_CalculationCyclicFormulae.php +++ /dev/null @@ -1,37 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Add some data, we will use some formulas here -$helper->log('Add some data and formulas'); -$spreadsheet->getActiveSheet()->setCellValue('A1', '=B1') - ->setCellValue('A2', '=B2+1') - ->setCellValue('B1', '=A1+1') - ->setCellValue('B2', '=A2'); - -Calculation::getInstance($spreadsheet)->cyclicFormulaCount = 15; - -// Calculated data -$helper->log('Calculated data'); -for ($row = 1; $row <= 2; ++$row) { - for ($col = 'A'; $col != 'C'; ++$col) { - $formula = $spreadsheet->getActiveSheet()->getCell($col . $row)->getValue(); - if ( - is_string($formula) - && ($formula[0] == '=') - ) { - $helper->log('Value of ' . $col . $row . ' [' . $formula . ']: ' . $spreadsheet->getActiveSheet()->getCell($col . $row)->getCalculatedValueString()); - } - } -} - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic1/16_Csv.php b/samples/Basic1/16_Csv.php deleted file mode 100644 index 86025b2655..0000000000 --- a/samples/Basic1/16_Csv.php +++ /dev/null @@ -1,45 +0,0 @@ -log('Write to CSV format'); -$writer = new CsvWriter($spreadsheet); -$writer->setDelimiter(',') - ->setEnclosure('"') - ->setSheetIndex(0); - -$callStartTime = microtime(true); -$filename = $helper->getTemporaryFilename('csv'); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); - -$helper->log('Read from CSV format'); - -$reader = new CsvReader(); -$reader->setDelimiter(',') - ->setEnclosure('"') - ->setSheetIndex(0); - -$callStartTime = microtime(true); -$spreadsheetFromCSV = $reader->load($filename); -$helper->logRead('Csv', $filename, $callStartTime); -unlink($filename); - -// Write Xlsx -$helper->write($spreadsheetFromCSV, __FILE__, ['Xlsx']); - -// Write CSV -$filenameCSV = $helper->getFilename(__FILE__, 'csv'); -$writerCSV = new CsvWriter($spreadsheetFromCSV); -//$writerCSV->setExcelCompatibility(true); -$writerCSV->setUseBom(true); // because of non-ASCII chars - -$callStartTime = microtime(true); -$writerCSV->save($filenameCSV); -$helper->logWrite($writerCSV, $filenameCSV, $callStartTime); diff --git a/samples/Basic1/17_Html.php b/samples/Basic1/17_Html.php deleted file mode 100644 index 5448f6f929..0000000000 --- a/samples/Basic1/17_Html.php +++ /dev/null @@ -1,9 +0,0 @@ -getProperties()->setTitle('Non-embedded images'); - -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ -$helper->write($spreadsheet, __FILE__, ['Html']); diff --git a/samples/Basic1/17a_Html.php b/samples/Basic1/17a_Html.php deleted file mode 100644 index 039f4bf1ba..0000000000 --- a/samples/Basic1/17a_Html.php +++ /dev/null @@ -1,19 +0,0 @@ -getProperties()->setTitle('Embedded images'); - -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ -$helper->write( - $spreadsheet, - __FILE__, - ['Html'], - false, - function (Html $writer): void { - $writer->setEmbedImages(true); - } -); diff --git a/samples/Basic1/17b_Html.php b/samples/Basic1/17b_Html.php deleted file mode 100644 index 94bd104afe..0000000000 --- a/samples/Basic1/17b_Html.php +++ /dev/null @@ -1,24 +0,0 @@ -write( - $spreadsheet, - __FILE__, - ['Html'], - false, - function (Html $writer): void { - $writer->setEmbedImages(true); - $writer->setEditHtmlCallback('changeGridlines'); - } -); diff --git a/samples/Basic2/20_Read_Excel2003XML.php b/samples/Basic2/20_Read_Excel2003XML.php deleted file mode 100644 index dc74ccb1f3..0000000000 --- a/samples/Basic2/20_Read_Excel2003XML.php +++ /dev/null @@ -1,13 +0,0 @@ -logRead('Xml', $filename, $callStartTime); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/22_Heavily_formatted.php b/samples/Basic2/22_Heavily_formatted.php deleted file mode 100644 index 5fb293e5b2..0000000000 --- a/samples/Basic2/22_Heavily_formatted.php +++ /dev/null @@ -1,49 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Maarten Balliauw') - ->setLastModifiedBy('Maarten Balliauw') - ->setTitle('Office 2007 XLSX Test Document') - ->setSubject('Office 2007 XLSX Test Document') - ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') - ->setKeywords('office 2007 openxml php') - ->setCategory('Test result file'); - -// Add some data -$helper->log('Add some data'); -$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], - ], - ] -); - -$spreadsheet->getActiveSheet()->getStyle('C5:R95')->applyFromArray( - ['fill' => [ - 'fillType' => Fill::FILL_SOLID, - 'color' => ['argb' => 'FFFFFF00'], - ], - ] -); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/23_Sharedstyles.php b/samples/Basic2/23_Sharedstyles.php deleted file mode 100644 index 5fc1555c57..0000000000 --- a/samples/Basic2/23_Sharedstyles.php +++ /dev/null @@ -1,60 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Maarten Balliauw') - ->setLastModifiedBy('Maarten Balliauw') - ->setTitle('Office 2007 XLSX Test Document') - ->setSubject('Office 2007 XLSX Test Document') - ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') - ->setKeywords('office 2007 openxml php') - ->setCategory('Test result file'); - -// Add some data -$helper->log('Add some data'); -$spreadsheet->setActiveSheetIndex(0); - -$sharedStyle1 = new Style(); -$sharedStyle2 = new Style(); - -$sharedStyle1->applyFromArray( - ['fill' => [ - '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], - ], - ] -); - -$spreadsheet->getActiveSheet()->duplicateStyle($sharedStyle1, 'A1:T100'); -$spreadsheet->getActiveSheet()->duplicateStyle($sharedStyle2, 'C5:R95'); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/25_In_memory_image.php b/samples/Basic2/25_In_memory_image.php deleted file mode 100644 index b6d483c18f..0000000000 --- a/samples/Basic2/25_In_memory_image.php +++ /dev/null @@ -1,82 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); -$sheet1 = $spreadsheet->getActiveSheet(); -$sheet1->setTitle('SheetWithData'); -$sheet1->getCell('G1')->setValue('X'); -$sheet1->getCell('E5')->setValue('Y'); -$sheet1->getCell('A8')->setValue('Z'); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Maarten Balliauw') - ->setLastModifiedBy('Maarten Balliauw') - ->setTitle('Office 2007 XLSX Test Document') - ->setSubject('Office 2007 XLSX Test Document') - ->setDescription('Test document for Office 2007 XLSX, generated using PHP classes.') - ->setKeywords('office 2007 openxml php') - ->setCategory('Test result file'); - -// Generate an image -$helper->log('Generate an image'); -$gdImage = imagecreatetruecolor(120, 20); -if (!$gdImage) { - throw new Exception('Cannot Initialize new GD image stream'); -} - -$textColor = imagecolorallocate($gdImage, 255, 255, 255); -if ($textColor === false) { - throw new Exception('imagecolorallocate failed'); -} -imagestring($gdImage, 1, 5, 5, 'Created with PhpSpreadsheet', $textColor); - -// Add a drawing to the worksheet -$helper->log('Add a drawing to the worksheet'); -$drawing = new MemoryDrawing(); -$drawing->setName('Sample image'); -$drawing->setDescription('Sample image'); -$drawing->setImageResource($gdImage); -$drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); -$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); -$drawing->setHeight(36); -$drawing->setWorksheet($sheet1); -$drawing->setCoordinates('C5'); - -$helper->log('Create new sheet'); -$sheet2 = $spreadsheet->createSheet(); -$sheet2->setTitle('SheetWithoutData'); - -// Add a drawing to the new worksheet -$helper->log('Add a drawing to the new worksheet'); -$drawing = new MemoryDrawing(); -$drawing->setName('Sample image'); -$drawing->setDescription('Sample image'); -$drawing->setImageResource($gdImage); -$drawing->setRenderingFunction(MemoryDrawing::RENDERING_JPEG); -$drawing->setMimeType(MemoryDrawing::MIMETYPE_DEFAULT); -$drawing->setHeight(36); -$drawing->setWorksheet($sheet2); -$drawing->setCoordinates('C5'); - -// Save -$helper->write( - $spreadsheet, - __FILE__, - ['Xlsx', 'Html'], - false, - function (BaseWriter $writer): void { - if (method_exists($writer, 'writeAllSheets')) { - $writer->writeAllSheets(); - } - } -); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic2/26_Utf8.php b/samples/Basic2/26_Utf8.php deleted file mode 100644 index eb53fe6050..0000000000 --- a/samples/Basic2/26_Utf8.php +++ /dev/null @@ -1,56 +0,0 @@ -log('Load Xlsx template file'); -$reader = IOFactory::createReader('Xlsx'); -$spreadsheet = $reader->load(__DIR__ . '/../templates/26template.xlsx'); -$spreadsheet->getActiveSheet()->setPrintGridlines(true); - -// at this point, we could do some manipulations with the template, but we skip this step -$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']); - -// Export to PDF (mpdf) -$mpdfCjkWriter = function (Mpdf $writer): void { - $mpdfCjk = function (string $html): string { - $html = str_replace("'Calibri'", "'Calibri',Sun-ExtA", $html); - - return str_replace("'Times New Roman'", "'Times New Roman',Sun-ExtA", $html); - }; - - $writer->setEditHtmlCallback($mpdfCjk); -}; - -$helper->log('Write to Mpdf'); -IOFactory::registerWriter('Pdf', Mpdf::class); -$filename = __FILE__; -$helper->write($spreadsheet, $filename, ['Pdf'], false, $mpdfCjkWriter); - -// Remove first two rows with field headers before exporting to CSV -$helper->log('Removing first two heading rows for CSV export'); -$worksheet = $spreadsheet->getActiveSheet(); -$worksheet->removeRow(1, 2); - -// Export to CSV (.csv) -$helper->log('Write to CSV format'); -/** @var Csv $writer */ -$helper->write($spreadsheet, __FILE__, ['Csv']); - -// Export to CSV with BOM (.csv) -$filename = str_replace('.php', '-bom.php', __FILE__); -$helper->log('Write to CSV format (with BOM)'); -$helper->write( - $spreadsheet, - $filename, - ['Csv'], - false, - function (Csv $writer): void { - $writer->setUseBOM(true); - } -); diff --git a/samples/Basic2/27_Images_Html_Pdf.php b/samples/Basic2/27_Images_Html_Pdf.php deleted file mode 100644 index 3f8da7dda6..0000000000 --- a/samples/Basic2/27_Images_Html_Pdf.php +++ /dev/null @@ -1,40 +0,0 @@ -log('Load Xlsx template file'); -$reader = IOFactory::createReader('Xls'); -$initialSpreadsheet = $reader->load(__DIR__ . '/../templates/27template.xls'); - -$xlsxFile = File::temporaryFilename(); -$writer = new XlsxWriter($initialSpreadsheet); -$helper->log('Save as Xlsx'); -$writer->save($xlsxFile); -$initialSpreadsheet->disconnectWorksheets(); -$reader2 = new XlsxReader(); -$helper->log('Load Xlsx'); -$spreadsheet = $reader2->load($xlsxFile); - -$helper->log('Hide grid lines'); -$spreadsheet->getActiveSheet()->setShowGridLines(false); - -$helper->log('Set orientation to landscape'); -$spreadsheet->getActiveSheet()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); - -$className = Mpdf::class; -$helper->log("Write to PDF format using {$className}, and to Html"); -IOFactory::registerWriter('Pdf', $className); - -// Save -$helper->write($spreadsheet, __FILE__, ['Pdf', 'Html']); -unlink($xlsxFile); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic2/27_Images_Xls.php b/samples/Basic2/27_Images_Xls.php deleted file mode 100644 index 929be0894a..0000000000 --- a/samples/Basic2/27_Images_Xls.php +++ /dev/null @@ -1,14 +0,0 @@ -log('Load Xls template file'); -$reader = IOFactory::createReader('Xls'); -$spreadsheet = $reader->load(__DIR__ . '/../templates/27template.xls'); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/27_Images_Xlsx.php b/samples/Basic2/27_Images_Xlsx.php deleted file mode 100644 index 370d7e35aa..0000000000 --- a/samples/Basic2/27_Images_Xlsx.php +++ /dev/null @@ -1,27 +0,0 @@ -log('Load Xlsx template file'); -$reader = IOFactory::createReader('Xlsx'); -// Note that Xlsx converts bmp to png, so it needs to be added -// programmatically rather than in template. -// Also note Xls converts both bmp and gif to png. -$spreadsheet = $reader->load(__DIR__ . '/../templates/27template.xlsx'); -$sheet = $spreadsheet->getActiveSheet(); -$drawing = new Drawing(); -$drawing->setName('Test BMP'); -$drawing->setPath(__DIR__ . '/../images/bmp.bmp'); -$drawing->setCoordinates('G17'); -$drawing->setWorksheet($sheet); - -$sheet->getCell('G16')->setValue('BMP'); -$sheet->getStyle('G16')->getFont()->setName('Arial Black')->setBold(true); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic2/28_Iterator.php b/samples/Basic2/28_Iterator.php deleted file mode 100644 index 1ea1903f8a..0000000000 --- a/samples/Basic2/28_Iterator.php +++ /dev/null @@ -1,34 +0,0 @@ -getTemporaryFilename(); -$writer = new XlsxWriter($sampleSpreadsheet); -$callStartTime = microtime(true); -$writer->save($filename); -$helper->logWrite($writer, $filename, $callStartTime); - -$callStartTime = microtime(true); -$reader = new XlsxReader(); -$spreadsheet = $reader->load($filename); -$helper->logRead('Xlsx', $filename, $callStartTime); -unlink($filename); -$helper->log('Iterate worksheets'); -foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { - $helper->log('Worksheet - ' . $worksheet->getTitle()); - - foreach ($worksheet->getRowIterator() as $row) { - $helper->log(' Row number - ' . $row->getRowIndex()); - - $cellIterator = $row->getCellIterator(); - $cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set - foreach ($cellIterator as $cell) { - $helper->log(' Cell - ' . $cell->getCoordinate() . ' - ' . $cell->getCalculatedValueString()); - } - } -} diff --git a/samples/Basic3/30_Templatebiff5.php b/samples/Basic3/30_Templatebiff5.php deleted file mode 100644 index a5272989ed..0000000000 --- a/samples/Basic3/30_Templatebiff5.php +++ /dev/null @@ -1,43 +0,0 @@ -log('Load from Xls template'); -$reader = IOFactory::createReader('Xls'); -$spreadsheet = $reader->load(__DIR__ . '/../templates/30templatebiff5.xls'); - -$helper->log('Add new data to the template'); -$data = [['title' => 'Excel for dummies', - 'price' => 17.99, - 'quantity' => 2, -], - ['title' => 'PHP for dummies', - 'price' => 15.99, - 'quantity' => 1, - ], - ['title' => 'Inside OOP', - 'price' => 12.95, - 'quantity' => 1, - ], -]; - -$spreadsheet->getActiveSheet()->setCellValue('D1', Date::PHPToExcel(time())); - -$baseRow = 5; -foreach ($data as $r => $dataRow) { - $row = $baseRow + $r; - $spreadsheet->getActiveSheet()->insertNewRowBefore($row, 1); - - $spreadsheet->getActiveSheet()->setCellValue('A' . $row, $r + 1) - ->setCellValue('B' . $row, $dataRow['title']) - ->setCellValue('C' . $row, $dataRow['price']) - ->setCellValue('D' . $row, $dataRow['quantity']) - ->setCellValue('E' . $row, '=C' . $row . '*D' . $row); -} -$spreadsheet->getActiveSheet()->removeRow($baseRow - 1, 1); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/Basic4/42b_RichText.php b/samples/Basic4/42b_RichText.php deleted file mode 100644 index 936975dec8..0000000000 --- a/samples/Basic4/42b_RichText.php +++ /dev/null @@ -1,22 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); -$sheet = $spreadsheet->getActiveSheet(); - -$rtf = new RichText(); -$rtf->createText('~Cell Style~'); -$rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true); -$rtf->createText('~No Style~'); - -$sheet->getCell('A1')->setValue($rtf); -$sheet->getStyle('A1')->getFont()->setBold(true); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Xls', 'Html']); diff --git a/samples/Basic4/44_Worksheet_info.php b/samples/Basic4/44_Worksheet_info.php deleted file mode 100644 index 4911d7de10..0000000000 --- a/samples/Basic4/44_Worksheet_info.php +++ /dev/null @@ -1,31 +0,0 @@ -getTemporaryFilename(); -$writer = new Writer($sampleSpreadsheet); -$writer->save($filename); - -$inputFileType = IOFactory::identify($filename); -$reader = new Reader(); -$sheetList = $reader->listWorksheetNames($filename); -$sheetInfo = $reader->listWorksheetInfo($filename); - -$helper->log('File Type:'); -var_dump($inputFileType); - -$helper->log('Worksheet Names:'); -var_dump($sheetList); - -$helper->log('Worksheet Names:'); -var_dump($sheetInfo); - -unlink($filename); diff --git a/samples/Basic4/45_Quadratic_equation_solver.php b/samples/Basic4/45_Quadratic_equation_solver.php deleted file mode 100644 index 9cb974c676..0000000000 --- a/samples/Basic4/45_Quadratic_equation_solver.php +++ /dev/null @@ -1,77 +0,0 @@ -isCli()) { - $helper->log('This example should only be run from a Web Browser' . PHP_EOL); - - return; -} -$postA = htmlentities(StringHelper::convertToString($_POST['A'] ?? '')); -$postB = htmlentities(StringHelper::convertToString($_POST['B'] ?? '')); -$postC = htmlentities(StringHelper::convertToString($_POST['C'] ?? '')); -?> -
- Enter the coefficients for Ax2 + Bx + C = 0 - - - - - - - - - - - - - -
- - - -
- - - -
- - -
-
- If A=0, the equation is not quadratic. -
- -log('Non-numeric input'); - } elseif ($postA == 0) { - $helper->log('The equation is not quadratic'); - } else { - // Calculate and Display the results - $helper->log('
Roots:
'); - - $discriminantFormula = '=POWER(' . $postB . ',2) - (4 * ' . $postA . ' * ' . $postC . ')'; - $discriminant = Calculation::getInstance()->calculateFormula($discriminantFormula); - $discriminant = StringHelper::convertToString($discriminant); - - $r1Formula = '=IMDIV(IMSUM(-' . $postB . ',IMSQRT(' . $discriminant . ')),2 * ' . $postA . ')'; - $r2Formula = '=IF(' . $discriminant . '=0,"Only one root",IMDIV(IMSUB(-' . $postB . ',IMSQRT(' . $discriminant . ')),2 * ' . $postA . '))'; - - /** @var string */ - $output = Calculation::getInstance()->calculateFormula($r1Formula); - $helper->log("$output"); - /** @var string */ - $output = Calculation::getInstance()->calculateFormula($r2Formula); - $helper->log("$output"); - $callEndTime = microtime(true); - $helper->logEndingNotes(); - } -} diff --git a/samples/Basic4/47_xlsfill.php b/samples/Basic4/47_xlsfill.php deleted file mode 100644 index 57a39ec76d..0000000000 --- a/samples/Basic4/47_xlsfill.php +++ /dev/null @@ -1,14 +0,0 @@ -log('Read spreadsheet'); -$reader = new Xls(); -$spreadsheet = $reader->load(__DIR__ . '/../templates/47_xlsfill.xls'); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xls']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic4/47_xlsxfill.php b/samples/Basic4/47_xlsxfill.php deleted file mode 100644 index 6be7536715..0000000000 --- a/samples/Basic4/47_xlsxfill.php +++ /dev/null @@ -1,14 +0,0 @@ -log('Read spreadsheet'); -$reader = new Xlsx(); -$spreadsheet = $reader->load(__DIR__ . '/../templates/47_xlsxfill.xlsx'); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xlsx']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic4/48_Image_move_size_with_cells.php b/samples/Basic4/48_Image_move_size_with_cells.php deleted file mode 100644 index 657de9772f..0000000000 --- a/samples/Basic4/48_Image_move_size_with_cells.php +++ /dev/null @@ -1,78 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); -$sheet = $spreadsheet->getActiveSheet(); -$sheet->getCell('A1')->setValue('twocell'); -$sheet->getCell('A2')->setValue('twocell'); -$sheet->getCell('A3')->setValue('onecell'); -$sheet->getCell('A6')->setValue('absolute'); - -// Add a drawing to the worksheet -$helper->log('Add a drawing to the worksheet two-cell anchor not resized'); -$drawing = new Drawing(); -$drawing->setName('PhpSpreadsheet'); -$drawing->setDescription('PhpSpreadsheet'); -$drawing->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png'); -// anchor type will be two-cell because Coordinates2 is set -//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL); -$drawing->setCoordinates('B1'); -$drawing->setCoordinates2('B1'); -$drawing->setOffsetX2($drawing->getImageWidth()); -$drawing->setOffsetY2($drawing->getImageHeight()); -$drawing->setWorksheet($spreadsheet->getActiveSheet()); - -// Add a drawing to the worksheet -$helper->log('Add a drawing to the worksheet two-cell anchor resized'); -$drawing2 = new Drawing(); -$drawing2->setName('PhpSpreadsheet'); -$drawing2->setDescription('PhpSpreadsheet'); -$drawing2->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png'); -// anchor type will be two-cell because Coordinates2 is set -//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL); -$drawing2->setCoordinates('C2'); -$drawing2->setCoordinates2('C2'); -$drawing2->setOffsetX2($drawing->getImageWidth()); -$drawing2->setOffsetY2($drawing->getImageHeight()); -$drawing2->setWorksheet($spreadsheet->getActiveSheet()); - -$spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth($drawing->getImageWidth(), Dimension::UOM_PIXELS); -$spreadsheet->getActiveSheet()->getRowDimension(2)->setRowHeight($drawing->getImageHeight(), Dimension::UOM_PIXELS); - -// Add a drawing to the worksheet one cell anchor -$helper->log('Add a drawing to the worksheet one-cell anchor'); -$drawing3 = new Drawing(); -$drawing3->setName('PhpSpreadsheet'); -$drawing3->setDescription('PhpSpreadsheet'); -$drawing3->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png'); -// anchor type will be one-cell because Coordinates2 is not set -//$drawing->setAnchorType(Drawing::ANCHORTYPE_ONECELL); -$drawing3->setCoordinates('D3'); -$drawing3->setWorksheet($spreadsheet->getActiveSheet()); - -// Add a drawing to the worksheet -$helper->log('Add a drawing to the worksheet two-cell anchor resized absolute'); -$drawing4 = new Drawing(); -$drawing4->setName('PhpSpreadsheet'); -$drawing4->setDescription('PhpSpreadsheet'); -$drawing4->setPath(__DIR__ . '/../images/PhpSpreadsheet_logo.png'); -// anchor type will be two-cell because Coordinates2 is set -//$drawing->setAnchorType(Drawing::ANCHORTYPE_TWOCELL); -$drawing4->setCoordinates('C6'); -$drawing4->setCoordinates2('C6'); -$drawing4->setOffsetX2($drawing->getImageWidth()); -$drawing4->setOffsetY2($drawing->getImageHeight()); -$drawing4->setWorksheet($spreadsheet->getActiveSheet()); -$drawing4->setEditAs(Drawing::EDIT_AS_ABSOLUTE); - -//$spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth($drawing->getImageWidth(), Dimension::UOM_PIXELS); -$spreadsheet->getActiveSheet()->getRowDimension(6)->setRowHeight($drawing->getImageHeight(), Dimension::UOM_PIXELS); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/Basic4/49_alignment.php b/samples/Basic4/49_alignment.php deleted file mode 100644 index 664f469264..0000000000 --- a/samples/Basic4/49_alignment.php +++ /dev/null @@ -1,80 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); -$spreadsheet->getProperties()->setTitle('Alignment'); -$sheet = $spreadsheet->getActiveSheet(); -$hi = 'Hi There'; -$ju = 'This is a longer than normal sentence'; -$sheet->fromArray([ - ['', 'default', 'bottom', 'top', 'center', 'justify', 'distributed'], - ['default', $hi, $hi, $hi, $hi, $hi, $hi], - ['left', $hi, $hi, $hi, $hi, $hi, $hi], - ['right', $hi, $hi, $hi, $hi, $hi, $hi], - ['center', $hi, $hi, $hi, $hi, $hi, $hi], - ['justify', $ju, $ju, $ju, $ju, $ju, $ju], - ['distributed', $ju, $ju, $ju, $ju, $ju, $ju], -]); -$sheet->getColumnDimension('B')->setWidth(20); -$sheet->getColumnDimension('C')->setWidth(20); -$sheet->getColumnDimension('D')->setWidth(20); -$sheet->getColumnDimension('E')->setWidth(20); -$sheet->getColumnDimension('F')->setWidth(20); -$sheet->getColumnDimension('G')->setWidth(20); -$sheet->getRowDimension(2)->setRowHeight(30); -$sheet->getRowDimension(3)->setRowHeight(30); -$sheet->getRowDimension(4)->setRowHeight(30); -$sheet->getRowDimension(5)->setRowHeight(30); -$sheet->getRowDimension(6)->setRowHeight(40); -$sheet->getRowDimension(7)->setRowHeight(40); -$minRow = 2; -$maxRow = 7; -$minCol = 'B'; -$maxCol = 'g'; -$sheet->getStyle("C$minRow:C$maxRow") - ->getAlignment() - ->setVertical(Alignment::VERTICAL_BOTTOM); -$sheet->getStyle("D$minRow:D$maxRow") - ->getAlignment() - ->setVertical(Alignment::VERTICAL_TOP); -$sheet->getStyle("E$minRow:E$maxRow") - ->getAlignment() - ->setVertical(Alignment::VERTICAL_CENTER); -$sheet->getStyle("F$minRow:F$maxRow") - ->getAlignment() - ->setVertical(Alignment::VERTICAL_JUSTIFY); -$sheet->getStyle("G$minRow:G$maxRow") - ->getAlignment() - ->setVertical(Alignment::VERTICAL_DISTRIBUTED); -$sheet->getStyle("{$minCol}3:{$maxCol}3") - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_LEFT); -$sheet->getStyle("{$minCol}4:{$maxCol}4") - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_RIGHT); -$sheet->getStyle("{$minCol}5:{$maxCol}5") - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_CENTER); -$sheet->getStyle("{$minCol}6:{$maxCol}6") - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_JUSTIFY); -$sheet->getStyle("{$minCol}7:{$maxCol}7") - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_DISTRIBUTED); - -$sheet->getCell('A9')->setValue('Center Continuous A9-C9'); -$sheet->getStyle('A9:C9') - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_CENTER_CONTINUOUS); -$sheet->getCell('A10')->setValue('Fill'); -$sheet->getStyle('A10') - ->getAlignment() - ->setHorizontal(Alignment::HORIZONTAL_FILL); -$sheet->setSelectedCells('A1'); - -$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html', 'Xls']); diff --git a/samples/Basic4/50_xlsverticalbreak.php b/samples/Basic4/50_xlsverticalbreak.php deleted file mode 100644 index b0d71915d2..0000000000 --- a/samples/Basic4/50_xlsverticalbreak.php +++ /dev/null @@ -1,14 +0,0 @@ -log('Read spreadsheet'); -$reader = new Xls(); -$spreadsheet = $reader->load(__DIR__ . '/../templates/50_xlsverticalbreak.xls'); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xls']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic4/51_ProtectedSort.php b/samples/Basic4/51_ProtectedSort.php deleted file mode 100644 index afd8bac0f4..0000000000 --- a/samples/Basic4/51_ProtectedSort.php +++ /dev/null @@ -1,92 +0,0 @@ -log('First sheet - protected, sorts not allowed'); -$sheet = $spreadsheet->getActiveSheet(); -$sheet->setTitle('sorttrue'); -$sheet->getCell('A1')->setValue(10); -$sheet->getCell('A2')->setValue(5); -$sheet->getCell('B1')->setValue(15); -$protection = $sheet->getProtection(); -$protection->setPassword('testpassword'); -$protection->setSheet(true); -$protection->setInsertRows(true); -$protection->setFormatCells(true); -$protection->setObjects(true); -$protection->setAutoFilter(false); -$protection->setSort(true); -$comment = $sheet->getComment('A1'); -$text = new RichText(); -$text->addText(new TextElement('Sort options should be grayed out. Sheet password to remove protections is testpassword for all sheets.')); -$comment->setText($text)->setHeight('120pt')->setWidth('120pt'); - -$helper->log('Second sheet - protected, sorts allowed, but no permitted range defined'); -$sheet = $spreadsheet->createSheet(); -$sheet->setTitle('sortfalse'); -$sheet->getCell('A1')->setValue(10); -$sheet->getCell('A2')->setValue(5); -$sheet->getCell('B1')->setValue(15); -$protection = $sheet->getProtection(); -$protection->setPassword('testpassword'); -$protection->setSheet(true); -$protection->setInsertRows(true); -$protection->setFormatCells(true); -$protection->setObjects(true); -$protection->setAutoFilter(false); -$protection->setSort(false); -$comment = $sheet->getComment('A1'); -$text = new RichText(); -$text->addText(new TextElement('Sort options not grayed out, but no permissible sort range.')); -$comment->setText($text)->setHeight('120pt')->setWidth('120pt'); - -$helper->log('Third sheet - protected, sorts allowed, but only on permitted range A:A, no range password needed'); -$sheet = $spreadsheet->createSheet(); -$sheet->setTitle('sortfalsenocolpw'); -$sheet->getCell('A1')->setValue(10); -$sheet->getCell('A2')->setValue(5); -$sheet->getCell('C1')->setValue(15); -$protection = $sheet->getProtection(); -$protection->setPassword('testpassword'); -$protection->setSheet(true); -$protection->setInsertRows(true); -$protection->setFormatCells(true); -$protection->setObjects(true); -$protection->setAutoFilter(false); -$protection->setSort(false); -$sheet->protectCells('A:A'); -$comment = $sheet->getComment('A1'); -$text = new RichText(); -$text->addText(new TextElement('Column A may be sorted without a password. No sort for any other column.')); -$comment->setText($text)->setHeight('120pt')->setWidth('120pt'); - -$helper->log('Fourth sheet - protected, sorts allowed, but only on permitted range A:A, and range password needed'); -$sheet = $spreadsheet->createSheet(); -$sheet->setTitle('sortfalsecolpw'); -$sheet->getCell('A1')->setValue(10); -$sheet->getCell('A2')->setValue(5); -$sheet->getCell('C1')->setValue(15); -$protection = $sheet->getProtection(); -$protection->setPassword('testpassword'); -$protection->setSheet(true); -$protection->setInsertRows(true); -$protection->setFormatCells(true); -$protection->setObjects(true); -$protection->setAutoFilter(false); -$protection->setSort(false); -$sheet->protectCells('A:A', 'sortpw', false, 'sortrange'); -$comment = $sheet->getComment('A1'); -$text = new RichText(); -$text->addText(new TextElement('Column A may be sorted with password sortpw. No sort for any other column.')); -$comment->setText($text)->setHeight('120pt')->setWidth('120pt'); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xls', 'Xlsx']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic4/52_Currency.php b/samples/Basic4/52_Currency.php deleted file mode 100644 index 5936ed2481..0000000000 --- a/samples/Basic4/52_Currency.php +++ /dev/null @@ -1,477 +0,0 @@ -log('First sheet - Accounting Wizard'); -$sheet = $spreadsheet->getActiveSheet(); -$sheet->setTitle('Accounting'); -$sheet->getCell('A1')->setValue('Currency'); -$sheet->getCell('B1')->setValue('Decimals'); -$sheet->getCell('C1')->setValue('ThouSep'); -$sheet->getCell('D1')->setValue('Lead'); -$sheet->getCell('E1')->setValue('Spacing'); -$sheet->getCell('F1')->setValue('Neg'); -$sheet->getCell('G1')->setValue('Pos'); -$sheet->getCell('H1')->setValue('Zero'); -$sheet->getCell('I1')->setValue('Neg'); -$sheet->getCell('J1')->setValue('Text'); -$sheet->getCell('L1')->setValue('ActWiz$'); -$sheet->getCell('M1')->setValue('ActWiz€Trl'); -$sheet->freezePane('A2'); -$sheet->getComment('E1')->getText()->createText('ignored, always true for Accounting'); -$sheet->getComment('F1')->getText()->createText('ignored, always () for Accounting'); - -$sheet->getCell('A2')->setValue('AcctUSD'); -$sheet->getCell('G2')->setValue(1234.56); -$sheet->getCell('H2')->setValue(0); -$sheet->getCell('I2')->setValue(-1234.56); -$sheet->getCell('J2')->setValue('text'); -$sheet->getStyle('G2:J2')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD); - -$sheet->getCell('A3')->setValue('AcctEur'); -$sheet->getCell('G3')->setValue(1234.56); -$sheet->getCell('H3')->setValue(0); -$sheet->getCell('I3')->setValue(-1234.56); -$sheet->getCell('J3')->setValue('Text'); -$sheet->getStyle('G3:J3')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_EUR); - -$sheet->getCell('A4')->setValue('AcctWiz¥'); -$sheet->getCell('E4')->setValue(true); -$sheet->getCell('G4')->setValue(1234.56); -$sheet->getCell('H4')->setValue(0); -$sheet->getCell('I4')->setValue(-1234.56); -$sheet->getCell('J4')->setValue('Text'); -$sheet->getStyle('G4:J4')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('¥', currencySymbolSpacing: true))->format(), - ], - ] -); - -$sheet->getCell('A5')->setValue('StalePR¥'); -$sheet->getCell('G5')->setValue(1234.56); -$sheet->getCell('H5')->setValue(0); -$sheet->getCell('I5')->setValue(-1234.56); -$sheet->getCell('J5')->setValue('Text'); -$sheet->getStyle('G5:J5')->getNumberFormat()->setFormatCode('_("¥"* #,##0.00_);_("¥"* -#,##0.00_);_("¥"* "-"??_);_(@_)'); - -$sheet->getCell('A6')->setValue('AcctWiz¥'); -$sheet->getCell('E6')->setValue(true); -$sheet->getCell('F6')->setValue(CurrencyNegative::minus->name); -$sheet->getCell('G6')->setValue(1234.56); -$sheet->getCell('H6')->setValue(0); -$sheet->getCell('I6')->setValue(-1234.56); -$sheet->getCell('J6')->setValue('Text'); -$sheet->getStyle('G6:J6')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('¥', currencySymbolSpacing: true, negative: CurrencyNegative::minus))->format(), - ], - ] -); - -$sheet->getCell('A7')->setValue('AcctWiz¥'); -$sheet->getCell('E7')->setValue(false); -$sheet->getCell('F7')->setValue(CurrencyNegative::minus->name); -$sheet->getCell('G7')->setValue(1234.56); -$sheet->getCell('H7')->setValue(0); -$sheet->getCell('I7')->setValue(-1234.56); -$sheet->getCell('J7')->setValue('Text'); -$sheet->getStyle('G7:J7')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('¥', currencySymbolSpacing: false, negative: CurrencyNegative::minus))->format(), - ], - ] -); - -$sheet->getCell('A8')->setValue('AcctWiz¥'); -$sheet->getCell('E8')->setValue(false); -$sheet->getCell('F8')->setValue(CurrencyNegative::parentheses->name); -$sheet->getCell('G8')->setValue(1234.56); -$sheet->getCell('H8')->setValue(0); -$sheet->getCell('I8')->setValue(-1234.56); -$sheet->getCell('J8')->setValue('Text'); -$sheet->getStyle('G8:J8')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('¥', currencySymbolSpacing: false, negative: CurrencyNegative::parentheses))->format(), - ], - ] -); - -$sheet->getCell('A9')->setValue('AcctW HUF'); -$sheet->getCell('E9')->setValue(true); -$sheet->getCell('G9')->setValue(1234.56); -$sheet->getCell('H9')->setValue(0); -$sheet->getCell('I9')->setValue(-1234.56); -$sheet->getCell('J9')->setValue('Text'); -$sheet->getStyle('G9:J9')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('HUF', currencySymbolSpacing: true))->format(), - ], - ] -); - -$sheet->getCell('A10')->setValue('AcctW HUF'); -$sheet->getCell('E10')->setValue(true); -$sheet->getCell('F10')->setValue(CurrencyNegative::redParentheses->name); -$sheet->getStyle('F10')->getFont()->getColor()->setRgb('FF0000'); -$sheet->getCell('G10')->setValue(1234.56); -$sheet->getCell('H10')->setValue(0); -$sheet->getCell('I10')->setValue(-1234.56); -$sheet->getCell('J10')->setValue('Text'); -$sheet->getStyle('G10:J10')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('HUF', currencySymbolSpacing: true, negative: CurrencyNegative::redParentheses))->format(), - ], - ] -); - -$sheet->getCell('A11')->setValue('AcctW Kazakh'); -$sheet->getCell('D11')->setValue(false); -$sheet->getCell('G11')->setValue(1234.56); -$sheet->getCell('H11')->setValue(0); -$sheet->getCell('I11')->setValue(-1234.56); -$sheet->getCell('J11')->setValue('Text'); -$sheet->getStyle('G11:J11')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Accounting('₸', currencySymbolPosition: Accounting::TRAILING_SYMBOL))->format(), - ], - ] -); - -$sheet->getCell('A12')->setValue('AcctW $'); -$sheet->getCell('B12')->setValue(3); -$sheet->getCell('C12')->setValue(false); -$sheet->getCell('D12')->setValue(false); -$sheet->getCell('F12')->setValue(CurrencyNegative::redMinus->name); -$sheet->getStyle('F12')->getFont()->getColor()->setRgb('FF0000'); -$sheet->getCell('G12')->setValue(1234.56); -$sheet->getCell('H12')->setValue(0); -$sheet->getCell('I12')->setValue(-1234.56); -$sheet->getCell('J12')->setValue('Text'); -$format = new Accounting( - '$', - decimals: 3, - thousandsSeparator: false, - currencySymbolPosition: Accounting::TRAILING_SYMBOL, - negative: CurrencyNegative::redMinus -); - -$sheet->getStyle('G12:J12')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => $format->format(), - ], - ] -); - -$sheet->getCell('L2')->setValue(1234.56); -$sheet->getCell('L3')->setValue(0); -$sheet->getCell('L4')->setValue(-1234.56); -$format = new Accounting('$'); -$sheet->getStyle('L2:L4')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => $format->format(), - ], - ] -); - -$sheet->getCell('M2')->setValue(1234.56); -$sheet->getCell('M3')->setValue(0); -$sheet->getCell('M4')->setValue(-1234.56); -$format = new Accounting('€', currencySymbolPosition: Accounting::TRAILING_SYMBOL); -$sheet->getStyle('M2:M4')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => $format->format(), - ], - ] -); - -$sheet->getColumnDimension('A')->setAutoSize(true); -$sheet->getColumnDimension('F')->setAutoSize(true); -$sheet->getColumnDimension('G')->setAutoSize(true); -$sheet->getColumnDimension('I')->setAutoSize(true); -$sheet->getColumnDimension('L')->setAutoSize(true); -$sheet->getColumnDimension('M')->setAutoSize(true); -$sheet->setSelectedCells('J1'); - -// second sheet - -$helper->log('Second sheet - Currency Wizard'); -$sheet = $spreadsheet->createSheet(); -$sheet->setTitle('Currency'); -$sheet->getCell('A1')->setValue('Currency'); -$sheet->getCell('B1')->setValue('Decimals'); -$sheet->getCell('C1')->setValue('ThouSep'); -$sheet->getCell('D1')->setValue('Lead'); -$sheet->getCell('E1')->setValue('Spacing'); -$sheet->getCell('F1')->setValue('Negative'); -$sheet->getCell('G1')->setValue('Pos'); -$sheet->getCell('H1')->setValue('Zero'); -$sheet->getCell('I1')->setValue('Neg'); -$sheet->getCell('J1')->setValue('Text'); -$sheet->freezePane('A2'); -$sheet->getComment('E1')->getText()->createText('ignored, always false for Currency'); - -$sheet->getCell('A2')->setValue('CurrUSD'); -$sheet->getCell('G2')->setValue(1234.56); -$sheet->getCell('H2')->setValue(0); -$sheet->getCell('I2')->setValue(-1234.56); -$sheet->getCell('J2')->setValue('text'); -$sheet->getStyle('G2:J2')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_USD); - -$sheet->getCell('A3')->setValue('CurrEur'); -$sheet->getCell('G3')->setValue(1234.56); -$sheet->getCell('H3')->setValue(0); -$sheet->getCell('I3')->setValue(-1234.56); -$sheet->getCell('J3')->setValue('Text'); -$sheet->getStyle('G3:J3')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_CURRENCY_EUR); - -$sheet->getCell('A4')->setValue('CurrWiz¥'); -$sheet->getCell('E4')->setValue(true); -$sheet->getCell('G4')->setValue(1234.56); -$sheet->getCell('H4')->setValue(0); -$sheet->getCell('I4')->setValue(-1234.56); -$sheet->getCell('J4')->setValue('Text'); -$sheet->getStyle('G4:J4')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('¥', currencySymbolSpacing: true))->format(), - ], - ] -); - -$sheet->getCell('A5')->setValue('StalePR¥'); -$sheet->getCell('G5')->setValue(1234.56); -$sheet->getCell('H5')->setValue(0); -$sheet->getCell('I5')->setValue(-1234.56); -$sheet->getCell('J5')->setValue('Text'); -$sheet->getStyle('G5:J5')->getNumberFormat()->setFormatCode('¥ #,##0'); - -$sheet->getCell('A6')->setValue('CurrWiz¥'); -$sheet->getCell('E6')->setValue(true); -$sheet->getCell('F6')->setValue(CurrencyNegative::minus->name); -$sheet->getCell('G6')->setValue(1234.56); -$sheet->getCell('H6')->setValue(0); -$sheet->getCell('I6')->setValue(-1234.56); -$sheet->getCell('J6')->setValue('Text'); -$sheet->getStyle('G6:J6')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('¥', currencySymbolSpacing: true, negative: CurrencyNegative::minus))->format(), - ], - ] -); - -$sheet->getCell('A7')->setValue('CurrWiz¥'); -$sheet->getCell('E7')->setValue(false); -$sheet->getCell('F7')->setValue(CurrencyNegative::minus->name); -$sheet->getCell('G7')->setValue(1234.56); -$sheet->getCell('H7')->setValue(0); -$sheet->getCell('I7')->setValue(-1234.56); -$sheet->getCell('J7')->setValue('Text'); -$sheet->getStyle('G7:J7')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('¥', currencySymbolSpacing: false, negative: CurrencyNegative::minus))->format(), - ], - ] -); - -$sheet->getCell('A8')->setValue('CurrWiz¥'); -$sheet->getCell('E8')->setValue(false); -$sheet->getCell('F8')->setValue(CurrencyNegative::parentheses->name); -$sheet->getCell('G8')->setValue(1234.56); -$sheet->getCell('H8')->setValue(0); -$sheet->getCell('I8')->setValue(-1234.56); -$sheet->getCell('J8')->setValue('Text'); -$sheet->getStyle('G8:J8')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('¥', currencySymbolSpacing: false, negative: CurrencyNegative::parentheses))->format(), - ], - ] -); - -$sheet->getCell('A9')->setValue('CurrW HUF'); -$sheet->getCell('E9')->setValue(true); -$sheet->getCell('G9')->setValue(1234.56); -$sheet->getCell('H9')->setValue(0); -$sheet->getCell('I9')->setValue(-1234.56); -$sheet->getCell('J9')->setValue('Text'); -$sheet->getStyle('G9:J9')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('HUF', currencySymbolSpacing: true))->format(), - ], - ] -); - -$sheet->getCell('A10')->setValue('CurrW HUF'); -$sheet->getCell('E10')->setValue(true); -$sheet->getCell('F10')->setValue(CurrencyNegative::redParentheses->name); -$sheet->getStyle('F10')->getFont()->getColor()->setRgb('FF0000'); -$sheet->getCell('G10')->setValue(1234.56); -$sheet->getCell('H10')->setValue(0); -$sheet->getCell('I10')->setValue(-1234.56); -$sheet->getCell('J10')->setValue('Text'); -$sheet->getStyle('G10:J10')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('HUF', currencySymbolSpacing: true, negative: CurrencyNegative::redParentheses))->format(), - ], - ] -); - -$sheet->getCell('A11')->setValue('CurrW Kazakh'); -$sheet->getCell('D11')->setValue(false); -$sheet->getCell('G11')->setValue(1234.56); -$sheet->getCell('H11')->setValue(0); -$sheet->getCell('I11')->setValue(-1234.56); -$sheet->getCell('J11')->setValue('Text'); -$sheet->getStyle('G11:J11')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new Currency('₸', currencySymbolPosition: Accounting::TRAILING_SYMBOL))->format(), - ], - ] -); - -$sheet->getCell('A12')->setValue('CurrW $'); -$sheet->getCell('B12')->setValue(3); -$sheet->getCell('C12')->setValue(false); -$sheet->getCell('D12')->setValue(false); -$sheet->getCell('F12')->setValue(CurrencyNegative::redMinus->name); -$sheet->getStyle('F12')->getFont()->getColor()->setRgb('FF0000'); -$sheet->getCell('G12')->setValue(1234.56); -$sheet->getCell('H12')->setValue(0); -$sheet->getCell('I12')->setValue(-1234.56); -$sheet->getCell('J12')->setValue('Text'); -$format = new Currency( - '$', - decimals: 3, - thousandsSeparator: false, - currencySymbolPosition: Currency::TRAILING_SYMBOL, - negative: CurrencyNegative::redMinus -); - -$sheet->getStyle('G12:J12')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => $format->format(), - ], - ] -); - -$sheet->getColumnDimension('A')->setAutoSize(true); -$sheet->getColumnDimension('F')->setAutoSize(true); -$sheet->getColumnDimension('G')->setAutoSize(true); -$sheet->getColumnDimension('H')->setAutoSize(true); -$sheet->getColumnDimension('I')->setAutoSize(true); -$sheet->setSelectedCells('J1'); - -// third sheet - -$helper->log('Third sheet - CurrencyBase Wizard'); -$sheet = $spreadsheet->createSheet(); -$sheet->setTitle('CurrencyBase'); -$sheet->getCell('A1')->setValue('Currency'); -$sheet->getCell('B1')->setValue('Decimals'); -$sheet->getCell('C1')->setValue('ThouSep'); -$sheet->getCell('D1')->setValue('Lead'); -$sheet->getCell('E1')->setValue('Spacing'); -$sheet->getCell('F1')->setValue('Negative'); -$sheet->getCell('G1')->setValue('Pos'); -$sheet->getCell('H1')->setValue('Zero'); -$sheet->getCell('I1')->setValue('Neg'); -$sheet->getCell('J1')->setValue('Text'); -$sheet->freezePane('A2'); - -$sheet->getCell('A2')->setValue('StaleAct¥'); -$sheet->getCell('G2')->setValue(1234.56); -$sheet->getCell('H2')->setValue(0); -$sheet->getCell('I2')->setValue(-1234.56); -$sheet->getCell('J2')->setValue('Text'); -$sheet->getStyle('G2:J2')->getNumberFormat()->setFormatCode('_("¥"* #,##0.00_);_("¥"* -#,##0.00_);_("¥"* "-"??_);_(@_)'); - -$sheet->getCell('A3')->setValue('CurBase ¥'); -$sheet->getCell('E3')->setValue(true); -$sheet->getCell('F3')->setValue(CurrencyNegative::minus->name); -$sheet->getCell('G3')->setValue(1234.56); -$sheet->getCell('H3')->setValue(0); -$sheet->getCell('I3')->setValue(-1234.56); -$sheet->getCell('J3')->setValue('Text'); -$sheet->getStyle('G3:J3')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new CurrencyBase('¥', currencySymbolSpacing: true, negative: CurrencyNegative::minus))->format(), - ], - ] -); -$sheet->getCell('G4')->setValue(-1234.56); -$sheet->getStyle('G4')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new CurrencyBase('¥', currencySymbolSpacing: true, negative: CurrencyNegative::minus))->format(), - ], - ] -); -$sheet->getCell('G5')->setValue(0); -$sheet->getStyle('G5')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new CurrencyBase('¥', currencySymbolSpacing: true, negative: CurrencyNegative::minus))->format(), - ], - ] -); - -$sheet->getCell('A6')->setValue('StaleCur¥'); -$sheet->getCell('G6')->setValue(1234.56); -$sheet->getCell('H6')->setValue(0); -$sheet->getCell('I6')->setValue(-1234.56); -$sheet->getCell('J6')->setValue('Text'); -$sheet->getStyle('G6:J6')->getNumberFormat()->setFormatCode('¥ #,##0'); - -$sheet->getCell('A7')->setValue('CurBase ¥'); -$sheet->getCell('B7')->setValue(0); -$sheet->getCell('G7')->setValue(1234.56); -$sheet->getCell('H7')->setValue(0); -$sheet->getCell('I7')->setValue(-1234.56); -$sheet->getCell('J7')->setValue('Text'); -$sheet->getStyle('G7:J7')->applyFromArray( - [ - 'numberFormat' => [ - 'formatCode' => (new CurrencyBase('¥', 0))->format(), - ], - ] -); - -$sheet->getColumnDimension('A')->setAutoSize(true); -$sheet->getColumnDimension('F')->setAutoSize(true); -$sheet->getColumnDimension('G')->setAutoSize(true); -$sheet->getColumnDimension('H')->setAutoSize(true); -$sheet->getColumnDimension('I')->setAutoSize(true); -$sheet->setSelectedCells('J1'); - -$spreadsheet->setActiveSheetIndex(0); - -$helper->write($spreadsheet, __FILE__, ['Xls', 'Xlsx']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Basic4/53_ImageOpacity.php b/samples/Basic4/53_ImageOpacity.php deleted file mode 100644 index 50cffc1b75..0000000000 --- a/samples/Basic4/53_ImageOpacity.php +++ /dev/null @@ -1,67 +0,0 @@ -getProperties()->setTitle('53_ImageOpacity'); - -$helper->log('Add image to spreadsheet 6 times with different opacities'); -$sheet = $spreadsheet->getActiveSheet(); -$sheet->setTitle('Squares different opacities'); -$sheet->setShowGridLines(false); - -$drawing = new Drawing(); -$drawing->setName('Blue Square opacity not specified'); -$drawing->setPath($path); -$drawing->setCoordinates('A1'); -$drawing->setCoordinates2('B5'); -$drawing->setWorksheet($sheet); - -$drawing = new Drawing(); -$drawing->setName('Blue Square opacity 80%'); -$drawing->setPath($path); -$drawing->setCoordinates('C1'); -$drawing->setCoordinates2('D5'); -$drawing->setOpacity(80000); -$drawing->setWorksheet($sheet); - -$drawing = new Drawing(); -$drawing->setWorksheet($sheet); -$drawing->setName('Blue Square opacity 60%'); -$drawing->setPath($path); -$drawing->setCoordinates('E1'); -$drawing->setCoordinates2('F5'); -$drawing->setOpacity(60000); - -$drawing = new Drawing(); -$drawing->setName('Blue Square opacity 40%'); -$drawing->setPath($path); -$drawing->setCoordinates('A8'); -$drawing->setCoordinates2('B12'); -$drawing->setOpacity(40000); -$drawing->setWorksheet($sheet); - -$drawing = new Drawing(); -$drawing->setName('Blue Square opacity 20%'); -$drawing->setPath($path); -$drawing->setCoordinates('C8'); -$drawing->setCoordinates2('D12'); -$drawing->setOpacity(20000); -$drawing->setWorksheet($sheet); - -$drawing = new Drawing(); -$drawing->setWorksheet($sheet); -$drawing->setName('Blue Square opacity 0%'); -$drawing->setPath($path); -$drawing->setCoordinates('E8'); -$drawing->setCoordinates2('F12'); -$drawing->setOpacity(0); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xlsx', 'Html', 'Dompdf', 'Mpdf']); -$spreadsheet->disconnectWorksheets(); diff --git a/samples/Bitwise/BITAND.php b/samples/Bitwise/BITAND.php deleted file mode 100644 index 267e9ea645..0000000000 --- a/samples/Bitwise/BITAND.php +++ /dev/null @@ -1,54 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [1, 5], - [3, 5], - [1, 6], - [9, 6], - [13, 25], - [23, 10], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=TEXT(DEC2BIN(A' . $row . '), "00000")'); - $worksheet->setCellValue('D' . $row, '=TEXT(DEC2BIN(B' . $row . '), "00000")'); - $worksheet->setCellValue('E' . $row, '=BITAND(A' . $row . ',B' . $row . ')'); - $worksheet->setCellValue('F' . $row, '=TEXT(DEC2BIN(E' . $row . '), "00000")'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Bitwise AND of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ') and ' - . $worksheet->getCell('B' . $row)->getValueString() - . '(' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ') is ' - . $worksheet->getCell('E' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ')' - ); -} diff --git a/samples/Bitwise/BITLSHIFT.php b/samples/Bitwise/BITLSHIFT.php deleted file mode 100644 index ca74612072..0000000000 --- a/samples/Bitwise/BITLSHIFT.php +++ /dev/null @@ -1,74 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [1], - [3], - [9], - [15], - [26], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=DEC2BIN(A' . $row . ')'); - $worksheet->setCellValue('C' . $row, '=BITLSHIFT(A' . $row . ',1)'); - $worksheet->setCellValue('D' . $row, '=DEC2BIN(C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=BITLSHIFT(A' . $row . ',2)'); - $worksheet->setCellValue('F' . $row, '=DEC2BIN(E' . $row . ')'); - $worksheet->setCellValue('G' . $row, '=BITLSHIFT(A' . $row . ',3)'); - $worksheet->setCellValue('H' . $row, '=DEC2BIN(G' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Bitwise Left Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 1 bit is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ')' - ); - $helper->log( - "(E$row): Bitwise Left Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 2 bits is ' - . $worksheet->getCell('E' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ')' - ); - $helper->log( - "(E$row): Bitwise Left Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 3 bits is ' - . $worksheet->getCell('G' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('H' . $row)->getCalculatedValueString() - . ')' - ); -} diff --git a/samples/Bitwise/BITOR.php b/samples/Bitwise/BITOR.php deleted file mode 100644 index 852336482e..0000000000 --- a/samples/Bitwise/BITOR.php +++ /dev/null @@ -1,54 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [1, 5], - [3, 5], - [1, 6], - [9, 6], - [13, 25], - [23, 10], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=TEXT(DEC2BIN(A' . $row . '), "00000")'); - $worksheet->setCellValue('D' . $row, '=TEXT(DEC2BIN(B' . $row . '), "00000")'); - $worksheet->setCellValue('E' . $row, '=BITOR(A' . $row . ',B' . $row . ')'); - $worksheet->setCellValue('F' . $row, '=TEXT(DEC2BIN(E' . $row . '), "00000")'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Bitwise OR of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ') and ' - . $worksheet->getCell('B' . $row)->getValueString() - . '(' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ') is ' - . $worksheet->getCell('E' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ')' - ); -} diff --git a/samples/Bitwise/BITRSHIFT.php b/samples/Bitwise/BITRSHIFT.php deleted file mode 100644 index 0e27932364..0000000000 --- a/samples/Bitwise/BITRSHIFT.php +++ /dev/null @@ -1,72 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [9], - [15], - [26], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=DEC2BIN(A' . $row . ')'); - $worksheet->setCellValue('C' . $row, '=BITRSHIFT(A' . $row . ',1)'); - $worksheet->setCellValue('D' . $row, '=DEC2BIN(C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=BITRSHIFT(A' . $row . ',2)'); - $worksheet->setCellValue('F' . $row, '=DEC2BIN(E' . $row . ')'); - $worksheet->setCellValue('G' . $row, '=BITRSHIFT(A' . $row . ',3)'); - $worksheet->setCellValue('H' . $row, '=DEC2BIN(G' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Bitwise Right Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 1 bit is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ')' - ); - $helper->log( - "(E$row): Bitwise Right Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 2 bits is ' - . $worksheet->getCell('E' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ')' - ); - $helper->log( - "(E$row): Bitwise Right Shift of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ') by 3 bits is ' - . $worksheet->getCell('G' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('H' . $row)->getCalculatedValueString() - . ')' - ); -} diff --git a/samples/Bitwise/BITXOR.php b/samples/Bitwise/BITXOR.php deleted file mode 100644 index 3c9402b583..0000000000 --- a/samples/Bitwise/BITXOR.php +++ /dev/null @@ -1,54 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [1, 5], - [3, 5], - [1, 6], - [9, 6], - [13, 25], - [23, 10], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=TEXT(DEC2BIN(A' . $row . '), "00000")'); - $worksheet->setCellValue('D' . $row, '=TEXT(DEC2BIN(B' . $row . '), "00000")'); - $worksheet->setCellValue('E' . $row, '=BITXOR(A' . $row . ',B' . $row . ')'); - $worksheet->setCellValue('F' . $row, '=TEXT(DEC2BIN(E' . $row . '), "00000")'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Bitwise XOR of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' (' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ') and ' - . $worksheet->getCell('B' . $row)->getValueString() - . '(' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ') is ' - . $worksheet->getCell('E' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ')' - ); -} diff --git a/samples/Calculations/Database/DAVERAGE.php b/samples/Calculations/Database/DAVERAGE.php new file mode 100644 index 0000000000..92d840149c --- /dev/null +++ b/samples/Calculations/Database/DAVERAGE.php @@ -0,0 +1,56 @@ +log('Returns the average of selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The Average yield of Apple trees over 10\' in height'); +$worksheet->setCellValue('B12', '=DAVERAGE(A4:E10,"Yield",A1:B2)'); + +$worksheet->setCellValue('A13', 'The Average age of all Apple and Pear trees in the orchard'); +$worksheet->setCellValue('B13', '=DAVERAGE(A4:E10,3,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:B2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DAVERAGE() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DAVERAGE() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DCOUNT.php b/samples/Calculations/Database/DCOUNT.php new file mode 100644 index 0000000000..d869a4bc71 --- /dev/null +++ b/samples/Calculations/Database/DCOUNT.php @@ -0,0 +1,55 @@ +log('Counts the cells that contain numbers in a database.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The Number of Apple trees over 10\' in height'); +$worksheet->setCellValue('B12', '=DCOUNT(A4:E10,"Yield",A1:B2)'); + +$worksheet->setCellValue('A13', 'The Number of Apple and Pear trees in the orchard'); +$worksheet->setCellValue('B13', '=DCOUNT(A4:E10,3,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:B2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DCOUNT() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DCOUNT() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DGET.php b/samples/Calculations/Database/DGET.php new file mode 100644 index 0000000000..9f543c91c2 --- /dev/null +++ b/samples/Calculations/Database/DGET.php @@ -0,0 +1,52 @@ +log('Extracts a single value from a column of a list or database that matches conditions that you specify.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The height of the Apple tree between 10\' and 16\' tall'); +$worksheet->setCellValue('B12', '=DGET(A4:E10,"Height",A1:F2)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$helper->log('ALL'); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DMAX.php b/samples/Calculations/Database/DMAX.php new file mode 100644 index 0000000000..c48928d41d --- /dev/null +++ b/samples/Calculations/Database/DMAX.php @@ -0,0 +1,55 @@ +log('Returns the maximum value from selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The tallest tree in the orchard'); +$worksheet->setCellValue('B12', '=DMAX(A4:E10,"Height",A4:E10)'); + +$worksheet->setCellValue('A13', 'The Oldest apple tree in the orchard'); +$worksheet->setCellValue('B13', '=DMAX(A4:E10,3,A1:A2)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$helper->log('ALL'); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DMIN.php b/samples/Calculations/Database/DMIN.php new file mode 100644 index 0000000000..7bcaa20692 --- /dev/null +++ b/samples/Calculations/Database/DMIN.php @@ -0,0 +1,55 @@ +log('Returns the minimum value from selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The shortest tree in the orchard'); +$worksheet->setCellValue('B12', '=DMIN(A4:E10,"Height",A4:E10)'); + +$worksheet->setCellValue('A13', 'The Youngest apple tree in the orchard'); +$worksheet->setCellValue('B13', '=DMIN(A4:E10,3,A1:A2)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$helper->log('ALL'); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DMIN() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DMIN() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DPRODUCT.php b/samples/Calculations/Database/DPRODUCT.php new file mode 100644 index 0000000000..7c14ded667 --- /dev/null +++ b/samples/Calculations/Database/DPRODUCT.php @@ -0,0 +1,52 @@ +log('Multiplies the values in a column of a list or database that match conditions that you specify.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The product of the yields of all Apple trees over 10\' in the orchard'); +$worksheet->setCellValue('B12', '=DPRODUCT(A4:E10,"Yield",A1:B2)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$helper->log('ALL'); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DMAX() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DSTDEV.php b/samples/Calculations/Database/DSTDEV.php new file mode 100644 index 0000000000..7f09fa59e1 --- /dev/null +++ b/samples/Calculations/Database/DSTDEV.php @@ -0,0 +1,56 @@ +log('Estimates the standard deviation based on a sample of selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The estimated standard deviation in the yield of Apple and Pear trees'); +$worksheet->setCellValue('B12', '=DSTDEV(A4:E10,"Yield",A1:A3)'); + +$worksheet->setCellValue('A13', 'The estimated standard deviation in height of Apple and Pear trees'); +$worksheet->setCellValue('B13', '=DSTDEV(A4:E10,2,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DSTDEV() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DSTDEV() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DSTDEVP.php b/samples/Calculations/Database/DSTDEVP.php new file mode 100644 index 0000000000..9e999a80a1 --- /dev/null +++ b/samples/Calculations/Database/DSTDEVP.php @@ -0,0 +1,55 @@ +log('Calculates the standard deviation based on the entire population of selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The standard deviation in the yield of Apple and Pear trees'); +$worksheet->setCellValue('B12', '=DSTDEVP(A4:E10,"Yield",A1:A3)'); + +$worksheet->setCellValue('A13', 'The standard deviation in height of Apple and Pear trees'); +$worksheet->setCellValue('B13', '=DSTDEVP(A4:E10,2,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DSTDEVP() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DSTDEVP() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DVAR.php b/samples/Calculations/Database/DVAR.php new file mode 100644 index 0000000000..2a5f8749b8 --- /dev/null +++ b/samples/Calculations/Database/DVAR.php @@ -0,0 +1,55 @@ +log('Estimates variance based on a sample from selected database entries.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The estimated variance in the yield of Apple and Pear trees'); +$worksheet->setCellValue('B12', '=DVAR(A4:E10,"Yield",A1:A3)'); + +$worksheet->setCellValue('A13', 'The estimated variance in height of Apple and Pear trees'); +$worksheet->setCellValue('B13', '=DVAR(A4:E10,2,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DVAR() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DVAR() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/Database/DVARP.php b/samples/Calculations/Database/DVARP.php new file mode 100644 index 0000000000..4f57113b91 --- /dev/null +++ b/samples/Calculations/Database/DVARP.php @@ -0,0 +1,56 @@ +log('Calculates variance based on the entire population of selected database entries,'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], + ['Apple', 18, 20, 14, 105.00], + ['Pear', 12, 12, 10, 96.00], + ['Cherry', 13, 14, 9, 105.00], + ['Apple', 14, 15, 10, 75.00], + ['Pear', 9, 8, 8, 76.80], + ['Apple', 8, 9, 6, 45.00], +]; +$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], + ['="=Apple"', '>10', null, null, null, '<16'], + ['="=Pear"', null, null, null, null, null], +]; + +$worksheet->fromArray($criteria, null, 'A1'); +$worksheet->fromArray($database, null, 'A4'); + +$worksheet->setCellValue('A12', 'The variance in the yield of Apple and Pear trees'); +$worksheet->setCellValue('B12', '=DVARP(A4:E10,"Yield",A1:A3)'); + +$worksheet->setCellValue('A13', 'The variance in height of Apple and Pear trees'); +$worksheet->setCellValue('B13', '=DVARP(A4:E10,2,A1:A3)'); + +$helper->log('Database'); + +$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); +var_dump($databaseData); + +// Test the formulae +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A12')->getValue()); +$helper->log('DVARP() Result is ' . $worksheet->getCell('B12')->getCalculatedValue()); + +$helper->log('Criteria'); + +$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); +var_dump($criteriaData); + +$helper->log($worksheet->getCell('A13')->getValue()); +$helper->log('DVARP() Result is ' . $worksheet->getCell('B13')->getCalculatedValue()); diff --git a/samples/Calculations/DateTime/DATE.php b/samples/Calculations/DateTime/DATE.php new file mode 100644 index 0000000000..5d758f76fd --- /dev/null +++ b/samples/Calculations/DateTime/DATE.php @@ -0,0 +1,41 @@ +log('Returns the serial number of a particular date.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$testDates = [[2012, 3, 26], [2012, 2, 29], [2012, 4, 1], [2012, 12, 25], + [2012, 10, 31], [2012, 11, 5], [2012, 1, 1], [2012, 3, 17], + [2011, 2, 29], [7, 5, 3], [2012, 13, 1], [2012, 11, 45], + [2012, 0, 0], [2012, 1, 0], [2012, 0, 1], + [2012, -2, 2], [2012, 2, -2], [2012, -2, -2], +]; +$testDateCount = count($testDates); + +$worksheet->fromArray($testDates, null, 'A1', true); + +for ($row = 1; $row <= $testDateCount; ++$row) { + $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); + $worksheet->setCellValue('E' . $row, '=D' . $row); +} +$worksheet->getStyle('E1:E' . $testDateCount) + ->getNumberFormat() + ->setFormatCode('yyyy-mmm-dd'); + +// Test the formulae +for ($row = 1; $row <= $testDateCount; ++$row) { + $helper->log('Year: ' . $worksheet->getCell('A' . $row)->getFormattedValue()); + $helper->log('Month: ' . $worksheet->getCell('B' . $row)->getFormattedValue()); + $helper->log('Day: ' . $worksheet->getCell('C' . $row)->getFormattedValue()); + $helper->log('Formula: ' . $worksheet->getCell('D' . $row)->getValue()); + $helper->log('Excel DateStamp: ' . $worksheet->getCell('D' . $row)->getFormattedValue()); + $helper->log('Formatted DateStamp: ' . $worksheet->getCell('E' . $row)->getFormattedValue()); + $helper->log(''); +} diff --git a/samples/Calculations/DateTime/DATEVALUE.php b/samples/Calculations/DateTime/DATEVALUE.php new file mode 100644 index 0000000000..5cdb936d3a --- /dev/null +++ b/samples/Calculations/DateTime/DATEVALUE.php @@ -0,0 +1,39 @@ +log('Converts a date in the form of text to a serial number.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$testDates = ['26 March 2012', '29 Feb 2012', 'April 1, 2012', '25/12/2012', + '2012-Oct-31', '5th November', 'January 1st', 'April 2012', + '17-03', '03-2012', '29 Feb 2011', '03-05-07', + '03-MAY-07', '03-13-07', +]; +$testDateCount = count($testDates); + +for ($row = 1; $row <= $testDateCount; ++$row) { + $worksheet->setCellValue('A' . $row, $testDates[$row - 1]); + $worksheet->setCellValue('B' . $row, '=DATEVALUE(A' . $row . ')'); + $worksheet->setCellValue('C' . $row, '=B' . $row); +} + +$worksheet->getStyle('C1:C' . $testDateCount) + ->getNumberFormat() + ->setFormatCode('yyyy-mmm-dd'); + +// Test the formulae +$helper->log('Warning: The PhpSpreadsheet DATEVALUE() function accepts a wider range of date formats than MS Excel DATEFORMAT() function.'); +for ($row = 1; $row <= $testDateCount; ++$row) { + $helper->log('Date String: ' . $worksheet->getCell('A' . $row)->getFormattedValue()); + $helper->log('Formula: ' . $worksheet->getCell('B' . $row)->getValue()); + $helper->log('Excel DateStamp: ' . $worksheet->getCell('B' . $row)->getFormattedValue()); + $helper->log('Formatted DateStamp' . $worksheet->getCell('C' . $row)->getFormattedValue()); + $helper->log(''); +} diff --git a/samples/Calculations/DateTime/TIME.php b/samples/Calculations/DateTime/TIME.php new file mode 100644 index 0000000000..3d4208ad10 --- /dev/null +++ b/samples/Calculations/DateTime/TIME.php @@ -0,0 +1,39 @@ +log('Returns the serial number of a particular time.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$testDates = [[3, 15], [13, 15], [15, 15, 15], [3, 15, 30], + [15, 15, 15], [5], [9, 15, 0], [9, 15, -1], + [13, -14, -15], [0, 0, -1], +]; +$testDateCount = count($testDates); + +$worksheet->fromArray($testDates, null, 'A1', true); + +for ($row = 1; $row <= $testDateCount; ++$row) { + $worksheet->setCellValue('D' . $row, '=TIME(A' . $row . ',B' . $row . ',C' . $row . ')'); + $worksheet->setCellValue('E' . $row, '=D' . $row); +} +$worksheet->getStyle('E1:E' . $testDateCount) + ->getNumberFormat() + ->setFormatCode('hh:mm:ss'); + +// Test the formulae +for ($row = 1; $row <= $testDateCount; ++$row) { + $helper->log('Hour: ' . $worksheet->getCell('A' . $row)->getFormattedValue()); + $helper->log('Minute: ' . $worksheet->getCell('B' . $row)->getFormattedValue()); + $helper->log('Second: ' . $worksheet->getCell('C' . $row)->getFormattedValue()); + $helper->log('Formula: ' . $worksheet->getCell('D' . $row)->getValue()); + $helper->log('Excel TimeStamp: ' . $worksheet->getCell('D' . $row)->getFormattedValue()); + $helper->log('Formatted TimeStamp: ' . $worksheet->getCell('E' . $row)->getFormattedValue()); + $helper->log(''); +} diff --git a/samples/Calculations/DateTime/TIMEVALUE.php b/samples/Calculations/DateTime/TIMEVALUE.php new file mode 100644 index 0000000000..f75393cd57 --- /dev/null +++ b/samples/Calculations/DateTime/TIMEVALUE.php @@ -0,0 +1,35 @@ +log('Converts a time in the form of text to a serial number.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +// Add some data +$testDates = ['3:15', '13:15', '15:15:15', '3:15 AM', '3:15 PM', '5PM', '9:15AM', '13:15AM', +]; +$testDateCount = count($testDates); + +for ($row = 1; $row <= $testDateCount; ++$row) { + $worksheet->setCellValue('A' . $row, $testDates[$row - 1]); + $worksheet->setCellValue('B' . $row, '=TIMEVALUE(A' . $row . ')'); + $worksheet->setCellValue('C' . $row, '=B' . $row); +} + +$worksheet->getStyle('C1:C' . $testDateCount) + ->getNumberFormat() + ->setFormatCode('hh:mm:ss'); + +// Test the formulae +for ($row = 1; $row <= $testDateCount; ++$row) { + $helper->log('Time String: ' . $worksheet->getCell('A' . $row)->getFormattedValue()); + $helper->log('Formula: ' . $worksheet->getCell('B' . $row)->getValue()); + $helper->log('Excel TimeStamp: ' . $worksheet->getCell('B' . $row)->getFormattedValue()); + $helper->log('Formatted TimeStamp: ' . $worksheet->getCell('C' . $row)->getFormattedValue()); + $helper->log(''); +} diff --git a/samples/Chart/32_Chart_read_write.php b/samples/Chart/32_Chart_read_write.php index 2e8444e0df..ba711c06e3 100644 --- a/samples/Chart/32_Chart_read_write.php +++ b/samples/Chart/32_Chart_read_write.php @@ -3,7 +3,7 @@ use PhpOffice\PhpSpreadsheet\IOFactory; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $inputFileType = 'Xlsx'; $inputFileNames = __DIR__ . '/../templates/32readwrite*[0-9].xlsx'; @@ -13,7 +13,7 @@ $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; } } else { - $inputFileNames = glob($inputFileNames) ?: []; + $inputFileNames = glob($inputFileNames); } foreach ($inputFileNames as $inputFileName) { $inputFileNameShort = basename($inputFileName); @@ -40,34 +40,31 @@ } else { natsort($chartNames); foreach ($chartNames as $i => $chartName) { - $chart = $worksheet->getChartByNameOrThrow($chartName); + $chart = $worksheet->getChartByName($chartName); if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; + $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; } else { $caption = 'Untitled'; } $helper->log(' ' . $chartName . ' - ' . $caption); $indentation = str_repeat(' ', strlen($chartName) + 3); - $groupCount = $chart->getPlotAreaOrThrow()->getPlotGroupCount(); + $groupCount = $chart->getPlotArea()->getPlotGroupCount(); if ($groupCount == 1) { - $chartType = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex(0)->getPlotType(); + $chartType = $chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); $helper->log($indentation . ' ' . $chartType); - $helper->renderChart($chart, __FILE__); } else { $chartTypes = []; for ($i = 0; $i < $groupCount; ++$i) { - $chartTypes[] = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex($i)->getPlotType(); + $chartTypes[] = $chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); } $chartTypes = array_unique($chartTypes); if (count($chartTypes) == 1) { $chartType = 'Multiple Plot ' . array_pop($chartTypes); $helper->log($indentation . ' ' . $chartType); - $helper->renderChart($chart, __FILE__); } elseif (count($chartTypes) == 0) { $helper->log($indentation . ' *** Type not yet implemented'); } else { $helper->log($indentation . ' Combination Chart'); - $helper->renderChart($chart, __FILE__); } } } diff --git a/samples/Chart/32_Chart_read_write_HTML.php b/samples/Chart/32_Chart_read_write_HTML.php index b524714b3b..5febbf938e 100644 --- a/samples/Chart/32_Chart_read_write_HTML.php +++ b/samples/Chart/32_Chart_read_write_HTML.php @@ -4,11 +4,9 @@ use PhpOffice\PhpSpreadsheet\Settings; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Change these values to select the Rendering library that you wish to use -//Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); -Settings::setChartRenderer(PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); $inputFileType = 'Xlsx'; $inputFileNames = __DIR__ . '/../templates/36write*.xlsx'; @@ -19,7 +17,7 @@ $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; } } else { - $inputFileNames = glob($inputFileNames) ?: []; + $inputFileNames = glob($inputFileNames); } foreach ($inputFileNames as $inputFileName) { $inputFileNameShort = basename($inputFileName); @@ -47,22 +45,22 @@ } else { natsort($chartNames); foreach ($chartNames as $i => $chartName) { - $chart = $worksheet->getChartByNameOrThrow($chartName); + $chart = $worksheet->getChartByName($chartName); if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; + $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; } else { $caption = 'Untitled'; } $helper->log(' ' . $chartName . ' - ' . $caption); $helper->log(str_repeat(' ', strlen($chartName) + 3)); - $groupCount = $chart->getPlotAreaOrThrow()->getPlotGroupCount(); + $groupCount = $chart->getPlotArea()->getPlotGroupCount(); if ($groupCount == 1) { - $chartType = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex(0)->getPlotType(); + $chartType = $chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); $helper->log(' ' . $chartType); } else { $chartTypes = []; for ($i = 0; $i < $groupCount; ++$i) { - $chartTypes[] = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex($i)->getPlotType(); + $chartTypes[] = $chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); } $chartTypes = array_unique($chartTypes); if (count($chartTypes) == 1) { @@ -80,7 +78,11 @@ // Save $filename = $helper->getFilename($inputFileName, 'html'); - $helper->write($spreadsheet, $filename, ['Html'], true); + $writer = IOFactory::createWriter($spreadsheet, 'Html'); + $writer->setIncludeCharts(true); + $callStartTime = microtime(true); + $writer->save($filename); + $helper->logWrite($writer, $filename, $callStartTime); $spreadsheet->disconnectWorksheets(); unset($spreadsheet); diff --git a/samples/Chart/32_Chart_read_write_PDF.php b/samples/Chart/32_Chart_read_write_PDF.php index 9410a3f7e1..ee3ad0e0d3 100644 --- a/samples/Chart/32_Chart_read_write_PDF.php +++ b/samples/Chart/32_Chart_read_write_PDF.php @@ -4,12 +4,11 @@ use PhpOffice\PhpSpreadsheet\Settings; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ -IOFactory::registerWriter('Pdf', PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); + +IOFactory::registerWriter('Pdf', \PhpOffice\PhpSpreadsheet\Writer\Pdf\Mpdf::class); // Change these values to select the Rendering library that you wish to use -//Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); -Settings::setChartRenderer(PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); $inputFileType = 'Xlsx'; $inputFileNames = __DIR__ . '/../templates/36write*.xlsx'; @@ -20,7 +19,7 @@ $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; } } else { - $inputFileNames = glob($inputFileNames) ?: []; + $inputFileNames = glob($inputFileNames); } foreach ($inputFileNames as $inputFileName) { $inputFileNameShort = basename($inputFileName); @@ -37,9 +36,6 @@ $reader->setIncludeCharts(true); $spreadsheet = $reader->load($inputFileName); - $helper->log('Merge chart cells (needed only for Pdf)'); - $spreadsheet->mergeChartCellsForPdf(); - $helper->log('Iterate worksheets looking at the charts'); foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { $sheetName = $worksheet->getTitle(); @@ -51,22 +47,22 @@ } else { natsort($chartNames); foreach ($chartNames as $i => $chartName) { - $chart = $worksheet->getChartByNameOrThrow($chartName); + $chart = $worksheet->getChartByName($chartName); if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; + $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; } else { $caption = 'Untitled'; } $helper->log(' ' . $chartName . ' - ' . $caption); $helper->log(str_repeat(' ', strlen($chartName) + 3)); - $groupCount = $chart->getPlotAreaOrThrow()->getPlotGroupCount(); + $groupCount = $chart->getPlotArea()->getPlotGroupCount(); if ($groupCount == 1) { - $chartType = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex(0)->getPlotType(); + $chartType = $chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); $helper->log(' ' . $chartType); } else { $chartTypes = []; for ($i = 0; $i < $groupCount; ++$i) { - $chartTypes[] = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex($i)->getPlotType(); + $chartTypes[] = $chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); } $chartTypes = array_unique($chartTypes); if (count($chartTypes) == 1) { @@ -84,7 +80,11 @@ // Save $filename = $helper->getFilename($inputFileName, 'pdf'); - $helper->write($spreadsheet, $filename, ['Pdf'], true); + $writer = IOFactory::createWriter($spreadsheet, 'Pdf'); + $writer->setIncludeCharts(true); + $callStartTime = microtime(true); + $writer->save($filename); + $helper->logWrite($writer, $filename, $callStartTime); $spreadsheet->disconnectWorksheets(); unset($spreadsheet); diff --git a/samples/Chart33a/33_Chart_create_area.php b/samples/Chart/33_Chart_create_area.php similarity index 82% rename from samples/Chart33a/33_Chart_create_area.php rename to samples/Chart/33_Chart_create_area.php index 852d5dd8c1..4478d2ddd6 100644 --- a/samples/Chart33a/33_Chart_create_area.php +++ b/samples/Chart/33_Chart_create_area.php @@ -3,23 +3,24 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -70,7 +71,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); +$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false); $title = new Title('Test %age-Stacked Area Chart'); $yAxisLabel = new Title('Value ($k)'); @@ -82,7 +83,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -91,12 +92,13 @@ $chart->setTopLeftPosition('A7'); $chart->setBottomRightPosition('H20'); -$chart->setNoBorder(true); - // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart/33_Chart_create_bar.php b/samples/Chart/33_Chart_create_bar.php new file mode 100644 index 0000000000..a05cf92786 --- /dev/null +++ b/samples/Chart/33_Chart_create_bar.php @@ -0,0 +1,15 @@ +getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33a/33_Chart_create_bar_stacked.php b/samples/Chart/33_Chart_create_bar_stacked.php similarity index 83% rename from samples/Chart33a/33_Chart_create_bar_stacked.php rename to samples/Chart/33_Chart_create_bar_stacked.php index b1ee0a3ab4..7ba4d8deb8 100644 --- a/samples/Chart33a/33_Chart_create_bar_stacked.php +++ b/samples/Chart/33_Chart_create_bar_stacked.php @@ -3,23 +3,24 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -73,7 +74,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend = new Legend(Legend::POSITION_RIGHT, null, false); $title = new Title('Test Chart'); $yAxisLabel = new Title('Value ($k)'); @@ -85,7 +86,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -97,7 +98,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33a/33_Chart_create_column.php b/samples/Chart/33_Chart_create_column.php similarity index 83% rename from samples/Chart33a/33_Chart_create_column.php rename to samples/Chart/33_Chart_create_column.php index 41e1dbcbec..9ffe9d3f68 100644 --- a/samples/Chart33a/33_Chart_create_column.php +++ b/samples/Chart/33_Chart_create_column.php @@ -3,23 +3,24 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -73,7 +74,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend = new Legend(Legend::POSITION_RIGHT, null, false); $title = new Title('Test Column Chart'); $yAxisLabel = new Title('Value ($k)'); @@ -85,7 +86,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -97,7 +98,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33a/33_Chart_create_column_2.php b/samples/Chart/33_Chart_create_column_2.php similarity index 76% rename from samples/Chart33a/33_Chart_create_column_2.php rename to samples/Chart/33_Chart_create_column_2.php index 7c15d3b950..bba9210ab8 100644 --- a/samples/Chart33a/33_Chart_create_column_2.php +++ b/samples/Chart/33_Chart_create_column_2.php @@ -3,31 +3,32 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -81,7 +82,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_BOTTOM, null, false); +$legend = new Legend(Legend::POSITION_BOTTOM, null, false); $title = new Title('Test Grouped Column Chart'); $xAxisLabel = new Title('Financial Period'); @@ -94,7 +95,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs $xAxisLabel, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -106,7 +107,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33a/33_Chart_create_composite.php b/samples/Chart/33_Chart_create_composite.php similarity index 82% rename from samples/Chart33a/33_Chart_create_composite.php rename to samples/Chart/33_Chart_create_composite.php index 25ad08d957..83dc34a928 100644 --- a/samples/Chart33a/33_Chart_create_composite.php +++ b/samples/Chart/33_Chart_create_composite.php @@ -3,31 +3,32 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -127,7 +128,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series1, $series2, $series3]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend = new Legend(Legend::POSITION_RIGHT, null, false); $title = new Title('Average Weather Chart for Crete'); @@ -138,7 +139,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel null // yAxisLabel ); @@ -150,7 +151,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33a/33_Chart_create_line.php b/samples/Chart/33_Chart_create_line.php similarity index 81% rename from samples/Chart33a/33_Chart_create_line.php rename to samples/Chart/33_Chart_create_line.php index ed9674ebf0..bdaf01117f 100644 --- a/samples/Chart33a/33_Chart_create_line.php +++ b/samples/Chart/33_Chart_create_line.php @@ -3,14 +3,14 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; -use PhpOffice\PhpSpreadsheet\Chart\Properties; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $spreadsheet = new Spreadsheet(); $worksheet = $spreadsheet->getActiveSheet(); $worksheet->fromArray( @@ -35,7 +35,6 @@ new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012 ]; -$dataSeriesLabels[0]->setFillColor('FF0000'); // Set the X-Axis Labels // Datatype // Cell reference for data @@ -58,12 +57,12 @@ new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4), ]; -$dataSeriesValues[2]->setLineWidth(60000 / Properties::POINTS_WIDTH_MULTIPLIER); +$dataSeriesValues[2]->setLineWidth(60000); // Build the dataseries $series = new DataSeries( DataSeries::TYPE_LINECHART, // plotType - null, // plotGrouping, was DataSeries::GROUPING_STACKED, not a usual choice for line chart + DataSeries::GROUPING_STACKED, // plotGrouping range(0, count($dataSeriesValues) - 1), // plotOrder $dataSeriesLabels, // plotLabel $xAxisTickValues, // plotCategory @@ -73,9 +72,9 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); +$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false); -$title = new Title('Test Line Chart'); +$title = new Title('Test Stacked Line Chart'); $yAxisLabel = new Title('Value ($k)'); // Create the chart @@ -85,7 +84,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -97,7 +96,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33b/33_Chart_create_multiple_charts.php b/samples/Chart/33_Chart_create_multiple_charts.php similarity index 88% rename from samples/Chart33b/33_Chart_create_multiple_charts.php rename to samples/Chart/33_Chart_create_multiple_charts.php index 99f9d60669..10a11e13ed 100644 --- a/samples/Chart33b/33_Chart_create_multiple_charts.php +++ b/samples/Chart/33_Chart_create_multiple_charts.php @@ -3,23 +3,24 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -70,7 +71,7 @@ // Set the series in the plot area $plotArea1 = new PlotArea(null, [$series1]); // Set the chart legend -$legend1 = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); +$legend1 = new Legend(Legend::POSITION_TOPRIGHT, null, false); $title1 = new Title('Test %age-Stacked Area Chart'); $yAxisLabel1 = new Title('Value ($k)'); @@ -82,7 +83,7 @@ $legend1, // legend $plotArea1, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel1 // yAxisLabel ); @@ -94,8 +95,6 @@ // Add the chart to the worksheet $worksheet->addChart($chart1); -$helper->renderChart($chart1, __FILE__); - // Set the Labels for each data series we want to plot // Datatype // Cell reference for data @@ -147,7 +146,7 @@ // Set the series in the plot area $plotArea2 = new PlotArea(null, [$series2]); // Set the chart legend -$legend2 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend2 = new Legend(Legend::POSITION_RIGHT, null, false); $title2 = new Title('Test Column Chart'); $yAxisLabel2 = new Title('Value ($k)'); @@ -159,7 +158,7 @@ $legend2, // legend $plotArea2, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel2 // yAxisLabel ); @@ -171,7 +170,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart2); -$helper->renderChart($chart2, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33b/33_Chart_create_pie.php b/samples/Chart/33_Chart_create_pie.php similarity index 88% rename from samples/Chart33b/33_Chart_create_pie.php rename to samples/Chart/33_Chart_create_pie.php index 3b55dc11f0..d4ec0752e2 100644 --- a/samples/Chart33b/33_Chart_create_pie.php +++ b/samples/Chart/33_Chart_create_pie.php @@ -4,23 +4,24 @@ use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\Layout; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -72,7 +73,7 @@ // Set the series in the plot area $plotArea1 = new PlotArea($layout1, [$series1]); // Set the chart legend -$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend1 = new Legend(Legend::POSITION_RIGHT, null, false); $title1 = new Title('Test Pie Chart'); @@ -83,7 +84,7 @@ $legend1, // legend $plotArea1, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel null // yAxisLabel - Pie charts don't have a Y-Axis ); @@ -95,8 +96,6 @@ // Add the chart to the worksheet $worksheet->addChart($chart1); -$helper->renderChart($chart1, __FILE__); - // Set the Labels for each data series we want to plot // Datatype // Cell reference for data @@ -155,7 +154,7 @@ null, // legend $plotArea2, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel null // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis ); @@ -167,7 +166,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart2); -$helper->renderChart($chart2, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33b/33_Chart_create_radar.php b/samples/Chart/33_Chart_create_radar.php similarity index 76% rename from samples/Chart33b/33_Chart_create_radar.php rename to samples/Chart/33_Chart_create_radar.php index 251ec9541a..e57914abb3 100644 --- a/samples/Chart33b/33_Chart_create_radar.php +++ b/samples/Chart/33_Chart_create_radar.php @@ -4,31 +4,32 @@ use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; use PhpOffice\PhpSpreadsheet\Chart\Layout; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -74,7 +75,7 @@ $xAxisTickValues, // plotCategory $dataSeriesValues, // plotValues null, // plotDirection - false, // smooth line + null, // smooth line DataSeries::STYLE_MARKER // plotStyle ); @@ -84,7 +85,7 @@ // Set the series in the plot area $plotArea = new PlotArea($layout, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); +$legend = new Legend(Legend::POSITION_RIGHT, null, false); $title = new Title('Test Radar Chart'); @@ -95,7 +96,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel null // yAxisLabel - Radar charts don't have a Y-Axis ); @@ -107,7 +108,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33b/33_Chart_create_scatter.php b/samples/Chart/33_Chart_create_scatter.php similarity index 81% rename from samples/Chart33b/33_Chart_create_scatter.php rename to samples/Chart/33_Chart_create_scatter.php index f1bc71de73..12fc2bdc52 100644 --- a/samples/Chart33b/33_Chart_create_scatter.php +++ b/samples/Chart/33_Chart_create_scatter.php @@ -3,23 +3,24 @@ use PhpOffice\PhpSpreadsheet\Chart\Chart; use PhpOffice\PhpSpreadsheet\Chart\DataSeries; use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues; -use PhpOffice\PhpSpreadsheet\Chart\Legend as ChartLegend; +use PhpOffice\PhpSpreadsheet\Chart\Legend; use PhpOffice\PhpSpreadsheet\Chart\PlotArea; use PhpOffice\PhpSpreadsheet\Chart\Title; +use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ + $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 @@ -60,14 +61,14 @@ $xAxisTickValues, // plotCategory $dataSeriesValues, // plotValues null, // plotDirection - false, // smooth line + null, // smooth line DataSeries::STYLE_LINEMARKER // plotStyle ); // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); +$legend = new Legend(Legend::POSITION_TOPRIGHT, null, false); $title = new Title('Test Scatter Chart'); $yAxisLabel = new Title('Value ($k)'); @@ -79,7 +80,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs null, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -91,7 +92,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart33b/33_Chart_create_stock.php b/samples/Chart/33_Chart_create_stock.php similarity index 75% rename from samples/Chart33b/33_Chart_create_stock.php rename to samples/Chart/33_Chart_create_stock.php index 428ff7f08d..7a9f727452 100644 --- a/samples/Chart33b/33_Chart_create_stock.php +++ b/samples/Chart/33_Chart_create_stock.php @@ -1,29 +1,28 @@ 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 @@ -80,13 +79,7 @@ // Set the series in the plot area $plotArea = new PlotArea(null, [$series]); // Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); -$legend->getBorderLines()->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$legend->getFillColor()->setColorProperties('cccccc'); -$legendText = new AxisText(); -$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); -$legendText->setShadowProperties(1); -$legend->setLegendText($legendText); +$legend = new Legend(Legend::POSITION_RIGHT, null, false); $title = new Title('Test Stock Chart'); $xAxisLabel = new Title('Counts'); @@ -99,7 +92,7 @@ $legend, // legend $plotArea, // plotArea true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs + 0, // displayBlanksAs $xAxisLabel, // xAxisLabel $yAxisLabel // yAxisLabel ); @@ -111,9 +104,10 @@ // Add the chart to the worksheet $worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); - -$worksheet->setSelectedCells('G2'); - // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart/34_Chart_update.php b/samples/Chart/34_Chart_update.php index 6ca99cd0e4..638d2e0adf 100644 --- a/samples/Chart/34_Chart_update.php +++ b/samples/Chart/34_Chart_update.php @@ -1,37 +1,38 @@ getTemporaryFilename(); -$writer = new XlsxWriter($sampleSpreadsheet); -$writer->setIncludeCharts(true); +$writer = new Xlsx($sampleSpreadsheet); $writer->save($filename); $helper->log('Load from Xlsx file'); -$reader = new XlsxReader(); +$reader = IOFactory::createReader('Xlsx'); $reader->setIncludeCharts(true); $spreadsheet = $reader->load($filename); -unlink($filename); $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' ); // Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); +$filename = $helper->getFilename(__FILE__); +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->setIncludeCharts(true); +$callStartTime = microtime(true); +$writer->save($filename); +$helper->logWrite($writer, $filename, $callStartTime); diff --git a/samples/Chart/35_Chart_render.php b/samples/Chart/35_Chart_render.php index 9b05fda11f..9638c679d7 100644 --- a/samples/Chart/35_Chart_render.php +++ b/samples/Chart/35_Chart_render.php @@ -4,15 +4,12 @@ use PhpOffice\PhpSpreadsheet\Settings; require __DIR__ . '/../Header.php'; -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ // Change these values to select the Rendering library that you wish to use -//Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); -Settings::setChartRenderer(PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); +Settings::setChartRenderer(\PhpOffice\PhpSpreadsheet\Chart\Renderer\JpGraph::class); $inputFileType = 'Xlsx'; $inputFileNames = __DIR__ . '/../templates/32readwrite*[0-9].xlsx'; -//$inputFileNames = __DIR__ . '/../templates/32readwriteStockChart5.xlsx'; if ((isset($argc)) && ($argc > 1)) { $inputFileNames = []; @@ -20,19 +17,7 @@ $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; } } else { - $inputFileNames = glob($inputFileNames) ?: []; -} -if (count($inputFileNames) === 1) { - /** @var string[] */ - $unresolvedErrors = []; -} else { - /** @var string[] */ - $unresolvedErrors = [ - // The following spreadsheet was created by 3rd party software, - // and doesn't include the data that usually accompanies a chart. - // That is good enough for Excel, but not for JpGraph. - '32readwriteBubbleChart2.xlsx', - ]; + $inputFileNames = glob($inputFileNames); } foreach ($inputFileNames as $inputFileName) { $inputFileNameShort = basename($inputFileName); @@ -42,13 +27,6 @@ continue; } - if (in_array($inputFileNameShort, $unresolvedErrors, true)) { - $helper->log('*****'); - $helper->log('***** File ' . $inputFileNameShort . ' does not yet work with this script'); - $helper->log('*****'); - - continue; - } $helper->log("Load Test from $inputFileType file " . $inputFileNameShort); @@ -57,7 +35,6 @@ $spreadsheet = $reader->load($inputFileName); $helper->log('Iterate worksheets looking at the charts'); - $renderedCharts = 0; foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { $sheetName = $worksheet->getTitle(); $helper->log('Worksheet: ' . $sheetName); @@ -67,39 +44,32 @@ $helper->log(' There are no charts in this worksheet'); } else { natsort($chartNames); - foreach ($chartNames as $j => $chartName) { - $i = $renderedCharts + $j; - $chart = $worksheet->getChartByNameOrThrow($chartName); + foreach ($chartNames as $i => $chartName) { + $chart = $worksheet->getChartByName($chartName); if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; + $caption = '"' . implode(' ', $chart->getTitle()->getCaption()) . '"'; } else { $caption = 'Untitled'; } $helper->log(' ' . $chartName . ' - ' . $caption); - $pngFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); - if ($i !== 0) { - $pngFile = substr($pngFile, 0, -3) . "$i.png"; - } - if (file_exists($pngFile)) { - unlink($pngFile); + $jpegFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); + if (file_exists($jpegFile)) { + unlink($jpegFile); } try { - $chart->render($pngFile); - $helper->log('Rendered image: ' . $pngFile); + $chart->render($jpegFile); + $helper->log('Rendered image: ' . $jpegFile); } catch (Exception $e) { $helper->log('Error rendering chart: ' . $e->getMessage()); } - - ++$renderedCharts; } } } $spreadsheet->disconnectWorksheets(); unset($spreadsheet); - gc_collect_cycles(); } $helper->log('Done rendering charts as images'); diff --git a/samples/Chart/35_Chart_render33.php b/samples/Chart/35_Chart_render33.php deleted file mode 100644 index 01d0e09fea..0000000000 --- a/samples/Chart/35_Chart_render33.php +++ /dev/null @@ -1,101 +0,0 @@ -getTemporaryFolder() . '/33_Chart_create_*.xlsx'; - -if ((isset($argc)) && ($argc > 1)) { - $inputFileNames = []; - for ($i = 1; $i < $argc; ++$i) { - $inputFileNames[] = __DIR__ . '/../templates/' . $argv[$i]; - } -} else { - $inputFileNames = glob($inputFileNamesString) ?: []; -} -if (count($inputFileNames) === 1) { - /** @var string[] */ - $unresolvedErrors = []; -} else { - /** @var string[] */ - $unresolvedErrors = [ - //'33_Chart_create_bar_stacked.xlsx', // fixed with mitoteam/jpgraph 10.3 - ]; -} -foreach ($inputFileNames as $inputFileName) { - $inputFileNameShort = basename($inputFileName); - - if (!file_exists($inputFileName)) { - $helper->log('File ' . $inputFileNameShort . ' does not exist'); - - continue; - } - if (in_array($inputFileNameShort, $unresolvedErrors, true)) { - $helper->log('*****'); - $helper->log('***** File ' . $inputFileNameShort . ' does not yet work with this script'); - $helper->log('*****'); - - continue; - } - - $helper->log("Load Test from $inputFileType file " . $inputFileNameShort); - - $reader = IOFactory::createReader($inputFileType); - $reader->setIncludeCharts(true); - $spreadsheet = $reader->load($inputFileName); - - $helper->log('Iterate worksheets looking at the charts'); - $renderedCharts = 0; - foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { - $sheetName = $worksheet->getTitle(); - $helper->log('Worksheet: ' . $sheetName); - - $chartNames = $worksheet->getChartNames(); - if (empty($chartNames)) { - $helper->log(' There are no charts in this worksheet'); - } else { - natsort($chartNames); - foreach ($chartNames as $j => $chartName) { - $i = $renderedCharts + $j; - $chart = $worksheet->getChartByNameOrThrow($chartName); - if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; - } else { - $caption = 'Untitled'; - } - $helper->log(' ' . $chartName . ' - ' . $caption); - - $pngFile = $helper->getFilename('35-' . $inputFileNameShort, 'png'); - if ($i !== 0) { - $pngFile = substr($pngFile, 0, -3) . "$i.png"; - } - if (file_exists($pngFile)) { - unlink($pngFile); - } - - try { - $chart->render($pngFile); - $helper->log('Rendered image: ' . $pngFile); - } catch (Exception $e) { - $helper->log('Error rendering chart: ' . $e->getMessage()); - } - - ++$renderedCharts; - } - } - } - - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); - gc_collect_cycles(); -} - -$helper->log('Done rendering charts as images'); diff --git a/samples/Chart/37_Chart_dynamic_title.php b/samples/Chart/37_Chart_dynamic_title.php deleted file mode 100644 index 0b8a48bb2a..0000000000 --- a/samples/Chart/37_Chart_dynamic_title.php +++ /dev/null @@ -1,83 +0,0 @@ -log('File ' . $inputFileNameShort . ' does not exist'); - - continue; - } - $reader = IOFactory::createReader($inputFileType); - $reader->setIncludeCharts(true); - $callStartTime = microtime(true); - $spreadsheet = $reader->load($inputFileName); - $helper->logRead($inputFileType, $inputFileName, $callStartTime); - - $helper->log('Iterate worksheets looking at the charts'); - foreach ($spreadsheet->getWorksheetIterator() as $worksheet) { - $sheetName = $worksheet->getTitle(); - $worksheet->getCell('A1')->setValue('Changed Title'); - $helper->log('Worksheet: ' . $sheetName); - - $chartNames = $worksheet->getChartNames(); - if (empty($chartNames)) { - $helper->log(' There are no charts in this worksheet'); - } else { - natsort($chartNames); - foreach ($chartNames as $i => $chartName) { - $chart = $worksheet->getChartByNameOrThrow($chartName); - if ($chart->getTitle() !== null) { - $caption = '"' . $chart->getTitle()->getCaptionText($spreadsheet) . '"'; - } else { - $caption = 'Untitled'; - } - $helper->log(' ' . $chartName . ' - ' . $caption); - $indentation = str_repeat(' ', strlen($chartName) + 3); - $groupCount = $chart->getPlotAreaOrThrow()->getPlotGroupCount(); - if ($groupCount == 1) { - $chartType = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex(0)->getPlotType(); - $helper->log($indentation . ' ' . $chartType); - $helper->renderChart($chart, __FILE__, $spreadsheet); - } else { - $chartTypes = []; - for ($i = 0; $i < $groupCount; ++$i) { - $chartTypes[] = $chart->getPlotAreaOrThrow()->getPlotGroupByIndex($i)->getPlotType(); - } - $chartTypes = array_unique($chartTypes); - if (count($chartTypes) == 1) { - $chartType = 'Multiple Plot ' . array_pop($chartTypes); - $helper->log($indentation . ' ' . $chartType); - $helper->renderChart($chart, __FILE__); - } elseif (count($chartTypes) == 0) { - $helper->log($indentation . ' *** Type not yet implemented'); - } else { - $helper->log($indentation . ' Combination Chart'); - $helper->renderChart($chart, __FILE__); - } - } - } - } - } - - $callStartTime = microtime(true); - $helper->write($spreadsheet, $inputFileName, ['Xlsx'], true); - - Settings::setChartRenderer(PhpOffice\PhpSpreadsheet\Chart\Renderer\MtJpGraphRenderer::class); - $callStartTime = microtime(true); - $helper->write($spreadsheet, $inputFileName, ['Html'], true); - - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); -} diff --git a/samples/Chart33a/33_Chart_create_area_2.php b/samples/Chart33a/33_Chart_create_area_2.php deleted file mode 100644 index e7bdb143c3..0000000000 --- a/samples/Chart33a/33_Chart_create_area_2.php +++ /dev/null @@ -1,103 +0,0 @@ -getTheme()->setThemeColorName(SpreadsheetTheme::COLOR_SCHEME_2013_2022_NAME); -$worksheet = $spreadsheet->getActiveSheet(); -$worksheet->fromArray( - [ - ['', 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 -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4), -]; - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_AREACHART, // plotType - DataSeries::GROUPING_PERCENT_STACKED, // plotGrouping - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues // plotValues -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test %age-Stacked Area Chart'); -$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('A7'); -$chart->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_bar.php b/samples/Chart33a/33_Chart_create_bar.php deleted file mode 100644 index 9a079ad884..0000000000 --- a/samples/Chart33a/33_Chart_create_bar.php +++ /dev/null @@ -1,9 +0,0 @@ -write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_bar_custom_colors.php b/samples/Chart33a/33_Chart_create_bar_custom_colors.php deleted file mode 100644 index 94f085b680..0000000000 --- a/samples/Chart33a/33_Chart_create_bar_custom_colors.php +++ /dev/null @@ -1,181 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['', 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) -$colors = [ - 'cccccc', '00abb8', 'b8292f', 'eb8500', -]; - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4, [], null, $colors), -]; - -// Build the dataseries -$series1 = new DataSeries( - DataSeries::TYPE_BARCHART, // plotType - null, // plotGrouping (Pie charts don't have any grouping) - range(0, count($dataSeriesValues1) - 1), // plotOrder - $dataSeriesLabels1, // plotLabel - $xAxisTickValues1, // plotCategory - $dataSeriesValues1 // plotValues -); - -// Set up a layout object for the Pie chart -$layout1 = new Layout(); -$layout1->setShowVal(true); -$layout1->setShowPercent(true); - -// Set the series in the plot area -$plotArea1 = new PlotArea($layout1, [$series1]); -// Set the chart legend -$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -$title1 = new Title('Test Bar Chart'); - -// Create the chart -$chart1 = new Chart( - 'chart1', // name - $title1, // title - $legend1, // legend - $plotArea1, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Pie charts don't have a Y-Axis -); - -// Set the position where the chart should appear in the worksheet -$chart1->setTopLeftPosition('A7'); -$chart1->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart1); - -$helper->renderChart($chart1, __FILE__); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues2 = [ - $dataSeriesValues2Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), -]; -$dataSeriesValues2Element->setFillColor($colors); - -// Build the dataseries -$series2 = new DataSeries( - DataSeries::TYPE_DONUTCHART, // plotType - null, // plotGrouping (Donut charts don't have any grouping) - range(0, count($dataSeriesValues2) - 1), // plotOrder - $dataSeriesLabels2, // plotLabel - $xAxisTickValues2, // plotCategory - $dataSeriesValues2 // plotValues -); - -// Set up a layout object for the Pie chart -$layout2 = new Layout(); -$layout2->setShowVal(true); -$layout2->setShowCatName(true); - -// Set the series in the plot area -$plotArea2 = new PlotArea($layout2, [$series2]); - -$title2 = new Title('Test Donut Chart'); - -// Create the chart -$chart2 = new Chart( - 'chart2', // name - $title2, // title - null, // legend - $plotArea2, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis -); - -// Set the position where the chart should appear in the worksheet -$chart2->setTopLeftPosition('I7'); -$chart2->setBottomRightPosition('P20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart2); - -$helper->renderChart($chart2, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_bar_labels_lines.php b/samples/Chart33a/33_Chart_create_bar_labels_lines.php deleted file mode 100644 index 1980643ab3..0000000000 --- a/samples/Chart33a/33_Chart_create_bar_labels_lines.php +++ /dev/null @@ -1,207 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['', 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) -$colors = [ - 'cccccc', '00abb8', 'b8292f', 'eb8500', -]; - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4, [], null, $colors), -]; -$labelLayout = new Layout(); -$labelLayout - ->setShowVal(true) - ->setLabelFontColor(new ChartColor('FFFF00')) - ->setLabelFillColor(new ChartColor('accent2', null, 'schemeClr')); -$dataSeriesValues1[0]->setLabelLayout($labelLayout); - -// Build the dataseries -$series1 = new DataSeries( - DataSeries::TYPE_BARCHART, // plotType - null, // plotGrouping (Pie charts don't have any grouping) - range(0, count($dataSeriesValues1) - 1), // plotOrder - $dataSeriesLabels1, // plotLabel - $xAxisTickValues1, // plotCategory - $dataSeriesValues1 // plotValues -); - -// Set up a layout object for the Pie chart -$layout1 = new Layout(); -$layout1->setShowVal(true); -$layout1->setShowPercent(true); - -// Set the series in the plot area -$plotArea1 = new PlotArea($layout1, [$series1]); -// Set the chart legend -$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -$title1 = new Title('Test Bar Chart'); - -// Create the chart -$chart1 = new Chart( - 'chart1', // name - $title1, // title - $legend1, // legend - $plotArea1, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Pie charts don't have a Y-Axis -); -$majorGridlinesY = new GridLines(); -$majorGridlinesY->setLineColorProperties('FF0000'); -$minorGridlinesY = new GridLines(); -$minorGridlinesY->setLineStyleProperty('dash', Properties::LINE_STYLE_DASH_ROUND_DOT); -$chart1 - ->getChartAxisY() - ->setMajorGridlines($majorGridlinesY) - ->setMinorGridlines($minorGridlinesY); -$majorGridlinesX = new GridLines(); -$majorGridlinesX->setLineColorProperties('FF00FF'); -$minorGridlinesX = new GridLines(); -$minorGridlinesX->activateObject(); -$chart1 - ->getChartAxisX() - ->setMajorGridlines($majorGridlinesX) - ->setMinorGridlines($minorGridlinesX); - -// Set the position where the chart should appear in the worksheet -$chart1->setTopLeftPosition('A7'); -$chart1->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart1); - -$helper->renderChart($chart1, __FILE__); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues2 = [ - $dataSeriesValues2Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), -]; -$dataSeriesValues2Element->setFillColor($colors); - -// Build the dataseries -$series2 = new DataSeries( - DataSeries::TYPE_DONUTCHART, // plotType - null, // plotGrouping (Donut charts don't have any grouping) - range(0, count($dataSeriesValues2) - 1), // plotOrder - $dataSeriesLabels2, // plotLabel - $xAxisTickValues2, // plotCategory - $dataSeriesValues2 // plotValues -); - -// Set up a layout object for the Pie chart -$layout2 = new Layout(); -$layout2->setShowVal(true); -$layout2->setShowCatName(true); -$layout2->setLabelFillColor(new ChartColor('FFFF00')); - -// Set the series in the plot area -$plotArea2 = new PlotArea($layout2, [$series2]); - -$title2 = new Title('Test Donut Chart'); - -// Create the chart -$chart2 = new Chart( - 'chart2', // name - $title2, // title - null, // legend - $plotArea2, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis -); - -// Set the position where the chart should appear in the worksheet -$chart2->setTopLeftPosition('I7'); -$chart2->setBottomRightPosition('P20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart2); - -$helper->renderChart($chart2, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_bubble.php b/samples/Chart33a/33_Chart_create_bubble.php deleted file mode 100644 index e54eac136a..0000000000 --- a/samples/Chart33a/33_Chart_create_bubble.php +++ /dev/null @@ -1,121 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['Number of Products', 'Sales in USD', 'Market share'], - [14, 12200, 15], - [20, 60000, 33], - [18, 24400, 10], - [22, 32000, 42], - [], - [12, 8200, 18], - [15, 50000, 30], - [19, 22400, 15], - [25, 25000, 50], - ] -); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker - -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, null, null, 1, ['2013']), // 2013 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, null, null, 1, ['2014']), // 2014 -]; - -// Set the X-Axis values -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesCategories = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$7:$A$10', null, 4), -]; - -// Set the Y-Axis values -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$7:$B$10', null, 4), -]; - -// Set the Z-Axis values (bubble size) -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesBubbles = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$7:$C$10', null, 4), -]; - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_BUBBLECHART, // plotType - null, // plotGrouping - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $dataSeriesCategories, // plotCategory - $dataSeriesValues // plotValues -); -$series->setPlotBubbleSizes($dataSeriesBubbles); - -// Set the series in the plot area -$plotArea = new PlotArea(); -$plotArea->setPlotSeries([$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -// Create the chart -$chart = new Chart( - 'chart1', // name - null, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('E1'); -$chart->setBottomRightPosition('M15'); - -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -$worksheet->getColumnDimension('A')->setAutoSize(true); -$worksheet->getColumnDimension('B')->setAutoSize(true); -$worksheet->getColumnDimension('C')->setAutoSize(true); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_composite.alternate.php b/samples/Chart33a/33_Chart_create_composite.alternate.php deleted file mode 100644 index 9dfa8736b7..0000000000 --- a/samples/Chart33a/33_Chart_create_composite.alternate.php +++ /dev/null @@ -1,159 +0,0 @@ -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], - ] -); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // Temperature -]; -$dataSeriesLabels2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // Rainfall -]; -$dataSeriesLabels3 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // Humidity -]; - -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$13', null, 12), // Jan to Dec -]; - -$order = 0; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues1 = [ - $order => new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$13', null, 12), -]; - -// Build the dataseries -$series1 = new DataSeries( - DataSeries::TYPE_BARCHART, // plotType - DataSeries::GROUPING_CLUSTERED, // plotGrouping - [$order => $order], // plotOrder - $dataSeriesLabels1, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues1 // plotValues -); -// Set additional dataseries parameters -// Make it a vertical column rather than a horizontal bar graph -$series1->setPlotDirection(DataSeries::DIRECTION_COL); - -$order = 1; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues2 = [ - $order => new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$13', null, 12), -]; - -// Build the dataseries -$series2 = new DataSeries( - DataSeries::TYPE_LINECHART, // plotType - DataSeries::GROUPING_STANDARD, // plotGrouping - [$order => $order], // plotOrder - $dataSeriesLabels2, // plotLabel - [], // plotCategory - $dataSeriesValues2 // plotValues -); - -$order = 2; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues3 = [ - $order => new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$13', null, 12), -]; - -// Build the dataseries -$series3 = new DataSeries( - DataSeries::TYPE_AREACHART, // plotType - DataSeries::GROUPING_STANDARD, // plotGrouping - [$order => $order], // plotOrder - $dataSeriesLabels3, // plotLabel - [], // plotCategory - $dataSeriesValues3 // plotValues -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series1, $series2, $series3]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -$title = new Title('Average Weather Chart for Crete'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('F2'); -$chart->setBottomRightPosition('O16'); - -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33a/33_Chart_create_line_dateaxis.php b/samples/Chart33a/33_Chart_create_line_dateaxis.php deleted file mode 100644 index 86415c4aae..0000000000 --- a/samples/Chart33a/33_Chart_create_line_dateaxis.php +++ /dev/null @@ -1,385 +0,0 @@ -getActiveSheet(); -$dataSheet->setTitle('Data'); -// changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 meausurements from each date -// Dates changed not to fall on exact quarter start -$dataSheet->fromArray( - [ - ['', 'date', 'metric1', 'metric2', 'metric3'], - ['=DATEVALUE(B2)', '2021-01-10', 12.1, 15.1, 21.1], - ['=DATEVALUE(B3)', '2021-04-21', 56.2, 73.2, 86.2], - ['=DATEVALUE(B4)', '2021-07-31', 52.2, 61.2, 69.2], - ['=DATEVALUE(B5)', '2021-10-11', 30.2, 22.2, 0.2], - ['=DATEVALUE(B6)', '2022-01-21', 40.1, 38.1, 65.1], - ['=DATEVALUE(B7)', '2022-04-11', 45.2, 44.2, 96.2], - ['=DATEVALUE(B8)', '2022-07-01', 52.2, 51.2, 55.2], - ['=DATEVALUE(B9)', '2022-10-31', 41.2, 72.2, 56.2], - ] -); - -$dataSheet->getStyle('A2:A9')->getNumberFormat()->setFormatCode(Properties::FORMAT_CODE_DATE_ISO8601); -$dataSheet->getColumnDimension('A')->setAutoSize(true); -$dataSheet->getColumnDimension('B')->setAutoSize(true); -$dataSheet->setSelectedCells('A1'); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$C$1', null, 1), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$D$1', null, 1), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$E$1', null, 1), -]; -// Set the X-Axis Labels -// NUMBER, not STRING -// added x-axis values for each of the 3 metrics -// added FORMATE_CODE_NUMBER -// Number of datapoints in series -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Data Marker Color fill/[fill,Border] -// Data Marker size -// Color(s) added -// added FORMAT_CODE_NUMBER -$dataSeriesValues = [ - new DataSeriesValues( - DataSeriesValues::DATASERIES_TYPE_NUMBER, - 'Data!$C$2:$C$9', - Properties::FORMAT_CODE_NUMBER, - 8, - null, - 'diamond', - null, - 5 - ), - new DataSeriesValues( - DataSeriesValues::DATASERIES_TYPE_NUMBER, - 'Data!$D$2:$D$9', - Properties::FORMAT_CODE_NUMBER, - 8, - null, - 'square', - '*accent1', - 6 - ), - new DataSeriesValues( - DataSeriesValues::DATASERIES_TYPE_NUMBER, - 'Data!$E$2:$E$9', - Properties::FORMAT_CODE_NUMBER, - 8, - null, - null, - null, - 7 - ), // let Excel choose marker shape -]; -// series 1 - metric1 -// marker details -$dataSeriesValues[0] - ->getMarkerFillColor() - ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0] - ->getMarkerBorderColor() - ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); - -// line details - dashed, smooth line (Bezier) with arrows, 40% transparent -$dataSeriesValues[0] - ->setSmoothLine(true) - ->setScatterLines(true) - ->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type -$dataSeriesValues[0]->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound - Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash - Properties::LINE_STYLE_CAP_SQUARE, // cap - Properties::LINE_STYLE_JOIN_MITER, // join - Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type - Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index - Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type - Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index -); - -// series 2 - metric2, straight line - no special effects, connected -$dataSeriesValues[1] // square marker border color - ->getMarkerBorderColor() - ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[1] // square marker fill color - ->getMarkerFillColor() - ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1] - ->setScatterLines(true) - ->setSmoothLine(false) - ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1]->setLineWidth(2.0); - -// series 3 - metric3, markers, no line -$dataSeriesValues[2] // triangle? fill - //->setPointMarker('triangle') // let Excel choose shape, which is predicted to be a triangle - ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[2] // triangle border - ->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[2]->setScatterLines(false); // points not connected -// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers -$xAxis = new Axis(); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601); - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Chart'); -$yAxisLabel = new Title('Value ($k)'); -$yAxis = new Axis(); -$yAxis->setMajorGridlines(new GridLines()); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - $yAxis, // yAxis -); - -// Set the position of the chart in the chart sheet -$chart->setTopLeftPosition('A1'); -$chart->setBottomRightPosition('P12'); - -// create a 'Chart' worksheet, add $chart to it -$spreadsheet->createSheet(); -$chartSheet = $spreadsheet->getSheet(1); -$chartSheet->setTitle('Scatter+Line Chart'); - -$chartSheet = $spreadsheet->getSheetByNameOrThrow('Scatter+Line Chart'); -// Add the chart to the worksheet -$chartSheet->addChart($chart); - -// ------- Demonstrate Date Xaxis in Line Chart, not possible using Scatter Chart ------------ - -// Set the Labels (Column header) for each data series we want to plot -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$E$1', null, 1), -]; - -// Set the X-Axis Labels - dates, N.B. 01/10/2021 === Jan 10, NOT Oct 1 !! -// x-axis values are the Excel numeric representation of the date - so set -// formatCode=General for the xAxis VALUES, but we want the labels to be -// DISPLAYED as 'yyyy-mm-dd' That is, read a number, display a date. -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), -]; - -// X axis (date) settings -$xAxisLabel = new Title('Date'); -$xAxis = new Axis(); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601); // yyyy-mm-dd - -// Set the Data values for each data series we want to plot -$dataSeriesValues = [ - new DataSeriesValues( - DataSeriesValues::DATASERIES_TYPE_NUMBER, - 'Data!$E$2:$E$9', - Properties::FORMAT_CODE_NUMBER, - 8, - null, - 'triangle', - null, - 7 - ), -]; - -// series - metric3, markers, no line -$dataSeriesValues[0] - ->setScatterlines(false); // disable connecting lines -$dataSeriesValues[0] - ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0] - ->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); - -// Build the dataseries -// must now use LineChart instead of ScatterChart, since ScatterChart does not -// support "dateAx" axis type. -$series = new DataSeries( - DataSeries::TYPE_LINECHART, // plotType - 'standard', // plotGrouping - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_LINEMARKER // plotStyle - // DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -$title = new Title('Test Line-Chart with Date Axis - metric3 values'); - -// X axis (date) settings -$xAxisLabel = new Title('Game Date'); -$xAxis = new Axis(); -// date axis values are Excel numbers, not yyyy-mm-dd Date strings -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601); - -$xAxis->setAxisType('dateAx'); // dateAx available ONLY for LINECHART, not SCATTERCHART - -// measure the time span in Quarters, of data. -$dateMinMax = dateRange(8, $spreadsheet); // array 'min'=>earliest date of first Q, 'max'=>latest date of final Q -// change xAxis tick marks to match Qtr boundaries - -$nQtrs = sprintf('%3.2f', (($dateMinMax['max'] - $dateMinMax['min']) / 30.5) / 4); -$tickMarkInterval = ($nQtrs > 20) ? '6' : '3'; // tick marks every ? months - -$xAxis->setAxisOptionsProperties( - Properties::AXIS_LABELS_NEXT_TO, // axis_label pos - null, // horizontalCrossesValue - null, // horizontalCrosses - null, // axisOrientation - 'in', // major_tick_mark - null, // minor_tick_mark - $dateMinMax['min'], // minimum calculate this from the earliest data: 'Data!$A$2' - $dateMinMax['max'], // maximum calculate this from the last data: 'Data!$A$'.($nrows+1) - $tickMarkInterval, // majorUnit determines tickmarks & Gridlines ? - null, // minorUnit - null, // textRotation - null, // hidden - 'days', // baseTimeUnit - 'months', // majorTimeUnit, - 'months', // minorTimeUnit -); - -$yAxisLabel = new Title('Value ($k)'); -$yAxis = new Axis(); -$yAxis->setMajorGridlines(new GridLines()); -$xAxis->setMajorGridlines(new GridLines()); -$minorGridLines = new GridLines(); -$minorGridLines->activateObject(); -$xAxis->setMinorGridlines($minorGridLines); - -// Create the chart -$chart = new Chart( - 'chart2', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - $yAxis, // yAxis -); - -// Set the position of the chart in the chart sheet below the first chart -$chart->setTopLeftPosition('A13'); -$chart->setBottomRightPosition('P25'); -$chart->setRoundedCorners(true); // Rounded corners in Chart Outline - -// Add the chart to the worksheet $chartSheet -$chartSheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -$spreadsheet->setActiveSheetIndex(1); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true, resetActiveSheet: false); -$spreadsheet->disconnectWorksheets(); - -/** @return array{'min': float|int, 'max': float|int} */ -function dateRange(int $nrows, Spreadsheet $wrkbk): array -{ - $dataSheet = $wrkbk->getSheetByNameOrThrow('Data'); - - // start the xaxis at the beginning of the quarter of the first date - /** @var string */ - $startDateStr = $dataSheet->getCell('B2')->getValue(); // yyyy-mm-dd date string - $startDate = DateTime::createFromFormat('Y-m-d', $startDateStr); // php date obj - if ($startDate === false) { - throw new Exception("invalid start date $startDateStr on spreadsheet"); - } - - // get date of first day of the quarter of the start date - $startMonth = (int) $startDate->format('n'); // suppress leading zero - $startYr = (int) $startDate->format('Y'); - $qtr = intdiv($startMonth, 3) + (($startMonth % 3 > 0) ? 1 : 0); - $qtrStartMonth = sprintf('%02d', 1 + (($qtr - 1) * 3)); - $qtrStartStr = "$startYr-$qtrStartMonth-01"; - $ExcelQtrStartDateVal = SharedDate::convertIsoDate($qtrStartStr); - - // end the xaxis at the end of the quarter of the last date - /** @var string */ - $lastDateStr = $dataSheet->getCell([2, $nrows + 1])->getValue(); - $lastDate = DateTime::createFromFormat('Y-m-d', $lastDateStr); - if ($lastDate === false) { - throw new Exception("invalid last date $lastDateStr on spreadsheet"); - } - $lastMonth = (int) $lastDate->format('n'); - $lastYr = (int) $lastDate->format('Y'); - $qtr = intdiv($lastMonth, 3) + (($lastMonth % 3 > 0) ? 1 : 0); - $qtrEndMonth = 3 + (($qtr - 1) * 3); - $qtrEndMonth = sprintf('%02d', $qtrEndMonth); - $lastDOMDate = DateTime::createFromFormat('Y-m-d', "$lastYr-$qtrEndMonth-01"); - if ($lastDOMDate === false) { - throw new Exception("invalid last dom date $lastYr-$qtrEndMonth-01 on spreadsheet"); - } - $lastDOM = $lastDOMDate->format('t'); - $qtrEndStr = "$lastYr-$qtrEndMonth-$lastDOM"; - $ExcelQtrEndDateVal = SharedDate::convertIsoDate($qtrEndStr); - - $minMaxDates = ['min' => $ExcelQtrStartDateVal, 'max' => $ExcelQtrEndDateVal]; - - return $minMaxDates; -} diff --git a/samples/Chart33b/33_Chart_create_pie_custom_colors.php b/samples/Chart33b/33_Chart_create_pie_custom_colors.php deleted file mode 100644 index eea1e79537..0000000000 --- a/samples/Chart33b/33_Chart_create_pie_custom_colors.php +++ /dev/null @@ -1,181 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['', 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) -$colors = [ - 'cccccc', '00abb8', 'b8292f', 'eb8500', -]; - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues1 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4, [], null, $colors), -]; - -// Build the dataseries -$series1 = new DataSeries( - DataSeries::TYPE_PIECHART, // plotType - null, // plotGrouping (Pie charts don't have any grouping) - range(0, count($dataSeriesValues1) - 1), // plotOrder - $dataSeriesLabels1, // plotLabel - $xAxisTickValues1, // plotCategory - $dataSeriesValues1 // plotValues -); - -// Set up a layout object for the Pie chart -$layout1 = new Layout(); -$layout1->setShowVal(true); -$layout1->setShowPercent(true); - -// Set the series in the plot area -$plotArea1 = new PlotArea($layout1, [$series1]); -// Set the chart legend -$legend1 = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); - -$title1 = new Title('Test Pie Chart'); - -// Create the chart -$chart1 = new Chart( - 'chart1', // name - $title1, // title - $legend1, // legend - $plotArea1, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Pie charts don't have a Y-Axis -); - -// Set the position where the chart should appear in the worksheet -$chart1->setTopLeftPosition('A7'); -$chart1->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart1); - -$helper->renderChart($chart1, __FILE__); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues2 = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Custom colors -$dataSeriesValues2 = [ - $dataSeriesValues2Element = new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), -]; -$dataSeriesValues2Element->setFillColor($colors); - -// Build the dataseries -$series2 = new DataSeries( - DataSeries::TYPE_DONUTCHART, // plotType - null, // plotGrouping (Donut charts don't have any grouping) - range(0, count($dataSeriesValues2) - 1), // plotOrder - $dataSeriesLabels2, // plotLabel - $xAxisTickValues2, // plotCategory - $dataSeriesValues2 // plotValues -); - -// Set up a layout object for the Pie chart -$layout2 = new Layout(); -$layout2->setShowVal(true); -$layout2->setShowCatName(true); - -// Set the series in the plot area -$plotArea2 = new PlotArea($layout2, [$series2]); - -$title2 = new Title('Test Donut Chart'); - -// Create the chart -$chart2 = new Chart( - 'chart2', // name - $title2, // title - null, // legend - $plotArea2, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null // yAxisLabel - Like Pie charts, Donut charts don't have a Y-Axis -); - -// Set the position where the chart should appear in the worksheet -$chart2->setTopLeftPosition('I7'); -$chart2->setBottomRightPosition('P20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart2); - -$helper->renderChart($chart2, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33b/33_Chart_create_scatter2.php b/samples/Chart33b/33_Chart_create_scatter2.php deleted file mode 100644 index 8eaef9ee39..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter2.php +++ /dev/null @@ -1,190 +0,0 @@ -getActiveSheet(); -// changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 meausurements from each date -$worksheet->fromArray( - [ - ['', 'metric1', 'metric2', 'metric3'], - ['=DATEVALUE("2021-01-01")', 12.1, 15.1, 21.1], - ['=DATEVALUE("2021-01-04")', 56.2, 73.2, 86.2], - ['=DATEVALUE("2021-01-07")', 52.2, 61.2, 69.2], - ['=DATEVALUE("2021-01-10")', 30.2, 32.2, 0.2], - ] -); -$worksheet->getStyle('A2:A5')->getNumberFormat()->setFormatCode(Properties::FORMAT_CODE_DATE_ISO8601); -$worksheet->getColumnDimension('A')->setAutoSize(true); -$worksheet->setSelectedCells('A1'); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // was 2010 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // was 2011 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // was 2012 -]; -// Set the X-Axis Labels -// changed from STRING to NUMBER -// added 2 additional x-axis values associated with each of the 3 metrics -// added FORMATE_CODE_NUMBER -$xAxisTickValues = [ - //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// added FORMAT_CODE_NUMBER -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', Properties::FORMAT_CODE_NUMBER, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4), -]; - -// series 1 -// marker details -$dataSeriesValues[0] - ->setPointMarker('diamond') - ->setPointSize(5) - ->getMarkerFillColor() - ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0] - ->getMarkerBorderColor() - ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); - -// line details - smooth line, connected -$dataSeriesValues[0] - ->setScatterLines(true) - ->setSmoothLine(true) - ->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type -$dataSeriesValues[0]->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound - Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash - Properties::LINE_STYLE_CAP_SQUARE, // cap - Properties::LINE_STYLE_JOIN_MITER, // join - Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type - Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index - Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type - Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index -); - -// series 2 - straight line - no special effects, connected, straight line -$dataSeriesValues[1] // square fill - ->setPointMarker('square') - ->setPointSize(6) - ->getMarkerBorderColor() - ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[1] // square border - ->getMarkerFillColor() - ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1] - ->setScatterLines(true) - ->setSmoothLine(false) - ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1]->setLineWidth(2.0); - -// series 3 - markers, no line -$dataSeriesValues[2] // triangle fill - //->setPointMarker('triangle') // let Excel choose shape - ->setPointSize(7) - ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[2] // triangle border - ->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[2]->setScatterLines(false); // points not connected - -// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers -$xAxis = new ChartAxis(); -//$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE ); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); -//$xAxis->setAxisOption('textRotation', '45'); -$xAxisText = new AxisText(); -$xAxisText->setRotation(45)->getFillColorObject()->setValue('00FF00')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); -$xAxis->setAxisText($xAxisText); - -$yAxis = new ChartAxis(); -$yAxis->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_SIMPLE, - Properties::LINE_STYLE_DASH_DASH_DOT, - Properties::LINE_STYLE_CAP_FLAT, - Properties::LINE_STYLE_JOIN_BEVEL -); -$yAxis->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$yAxisText = new AxisText(); -$yAxisText->setGlowProperties(20.0, 'accent1', 20, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$yAxis->setAxisText($yAxisText); - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have any grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Trend Chart'); -$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - $yAxis, // yAxis -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('A7'); -$chart->setBottomRightPosition('P20'); -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33b/33_Chart_create_scatter3.php b/samples/Chart33b/33_Chart_create_scatter3.php deleted file mode 100644 index 123d2cb168..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter3.php +++ /dev/null @@ -1,187 +0,0 @@ -getActiveSheet(); -// changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 meausurements from each date -$worksheet->fromArray( - [ - ['', 'metric1', 'metric2', 'metric3'], - ['=DATEVALUE("2021-01-01")', 12.1, 15.1, 21.1], - ['=DATEVALUE("2021-01-04")', 56.2, 73.2, 86.2], - ['=DATEVALUE("2021-01-07")', 52.2, 61.2, 69.2], - ['=DATEVALUE("2021-01-10")', 30.2, 32.2, 0.2], - ] -); -$worksheet->getStyle('A2:A5')->getNumberFormat()->setFormatCode(Properties::FORMAT_CODE_DATE_ISO8601); -$worksheet->getColumnDimension('A')->setAutoSize(true); -$worksheet->setSelectedCells('A1'); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // was 2010 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // was 2011 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // was 2012 -]; -// Set the X-Axis Labels -// changed from STRING to NUMBER -// added 2 additional x-axis values associated with each of the 3 metrics -// added FORMATE_CODE_NUMBER -$xAxisTickValues = [ - //new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$A$2:$A$5', Properties::FORMAT_CODE_DATE, 4), -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// added FORMAT_CODE_NUMBER -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', Properties::FORMAT_CODE_NUMBER, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', Properties::FORMAT_CODE_NUMBER, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', Properties::FORMAT_CODE_NUMBER, 4), -]; - -// series 1 -// marker details -$dataSeriesValues[0] - ->setPointMarker('diamond') - ->setPointSize(5) - ->getMarkerFillColor() - ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0] - ->getMarkerBorderColor() - ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); - -// line details - smooth line, connected -$dataSeriesValues[0] - ->setScatterLines(true) - ->setSmoothLine(true) - ->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type -$dataSeriesValues[0]->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound - Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash - Properties::LINE_STYLE_CAP_SQUARE, // cap - Properties::LINE_STYLE_JOIN_MITER, // join - Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type - Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index - Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type - Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index -); - -// series 2 - straight line - no special effects, connected, straight line -$dataSeriesValues[1] // square fill - ->setPointMarker('square') - ->setPointSize(6) - ->getMarkerBorderColor() - ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[1] // square border - ->getMarkerFillColor() - ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1] - ->setScatterLines(true) - ->setSmoothLine(false) - ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1]->setLineWidth(2.0); - -// series 3 - markers, no line -$dataSeriesValues[2] // triangle fill - //->setPointMarker('triangle') // let Excel choose shape - ->setPointSize(7) - ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[2] // triangle border - ->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[2]->setScatterLines(false); // points not connected - -// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers -$xAxis = new ChartAxis(); -//$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE ); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); -$xAxis->setAxisOption('textRotation', '45'); -$xAxis->setAxisOption('hidden', '1'); - -$yAxis = new ChartAxis(); -$yAxis->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_SIMPLE, - Properties::LINE_STYLE_DASH_DASH_DOT, - Properties::LINE_STYLE_CAP_FLAT, - Properties::LINE_STYLE_JOIN_BEVEL -); -$yAxis->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$yAxis->setAxisOption('hidden', '1'); - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have any grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -$plotArea->setNoFill(true); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Trend Chart'); -//$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null, //$yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - $yAxis, // yAxis -); -$chart->setNoFill(true); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('A7'); -$chart->setBottomRightPosition('P20'); -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33b/33_Chart_create_scatter4.php b/samples/Chart33b/33_Chart_create_scatter4.php deleted file mode 100644 index 29168b9178..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter4.php +++ /dev/null @@ -1,126 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['', 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 -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012 -]; -// Set the X-Axis Labels -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4), -]; - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have any grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_LINEMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); - -$pos1 = 0; // pos = 0% (extreme low side or lower left corner) -$brightness1 = 0; // 0% -$gsColor1 = new ChartColor(); -$gsColor1->setColorProperties('FF0000', 75, 'srgbClr', $brightness1); // red -$gradientStop1 = [$pos1, $gsColor1]; - -$pos2 = 0.5; // pos = 50% (middle) -$brightness2 = 0.5; // 50% -$gsColor2 = new ChartColor(); -$gsColor2->setColorProperties('FFFF00', 50, 'srgbClr', $brightness2); // yellow -$gradientStop2 = [$pos2, $gsColor2]; - -$pos3 = 1.0; // pos = 100% (extreme high side or upper right corner) -$brightness3 = 0.5; // 50% -$gsColor3 = new ChartColor(); -$gsColor3->setColorProperties('00B050', 50, 'srgbClr', $brightness3); // green -$gradientStop3 = [$pos3, $gsColor3]; - -$gradientFillStops = [ - $gradientStop1, - $gradientStop2, - $gradientStop3, -]; -$gradientFillAngle = 315.0; // 45deg above horiz - -$plotArea->setGradientFillProperties($gradientFillStops, $gradientFillAngle); - -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Chart'); -$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('A7'); -$chart->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33b/33_Chart_create_scatter5_trendlines.php b/samples/Chart33b/33_Chart_create_scatter5_trendlines.php deleted file mode 100644 index 061810665b..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter5_trendlines.php +++ /dev/null @@ -1,275 +0,0 @@ -getActiveSheet(); -$dataSheet->setTitle('Data'); -// changed data to simulate a trend chart - Xaxis are dates; Yaxis are 3 meausurements from each date -$dataSheet->fromArray( - [ - ['', 'metric1', 'metric2', 'metric3'], - ['=DATEVALUE("2021-01-01")', 12.1, 15.1, 21.1], - ['=DATEVALUE("2021-04-01")', 56.2, 73.2, 86.2], - ['=DATEVALUE("2021-07-01")', 52.2, 61.2, 69.2], - ['=DATEVALUE("2021-10-01")', 30.2, 22.2, 0.2], - ['=DATEVALUE("2022-01-01")', 40.1, 38.1, 65.1], - ['=DATEVALUE("2022-04-01")', 45.2, 44.2, 96.2], - ['=DATEVALUE("2022-07-01")', 52.2, 51.2, 55.2], - ['=DATEVALUE("2022-10-01")', 41.2, 72.2, 56.2], - ] -); - -$dataSheet->getStyle('A2:A9')->getNumberFormat()->setFormatCode(Properties::FORMAT_CODE_DATE_ISO8601); -$dataSheet->getColumnDimension('A')->setAutoSize(true); -$dataSheet->setSelectedCells('A1'); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$B$1', null, 1), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$C$1', null, 1), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$D$1', null, 1), -]; -// Set the X-Axis Labels -// NUMBER, not STRING -// added x-axis values for each of the 3 metrics -// added FORMATE_CODE_NUMBER -// Number of datapoints in series -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -// Data Marker Color fill/[fill,Border] -// Data Marker size -// Color(s) added -// added FORMAT_CODE_NUMBER -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$B$2:$B$9', Properties::FORMAT_CODE_NUMBER, 8, null, 'diamond', null, 5), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$C$2:$C$9', Properties::FORMAT_CODE_NUMBER, 8, null, 'square', '*accent1', 6), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$D$2:$D$9', Properties::FORMAT_CODE_NUMBER, 8, null, null, null, 7), // let Excel choose marker shape -]; -// series 1 - metric1 -// marker details -$dataSeriesValues[0] - ->getMarkerFillColor() - ->setColorProperties('0070C0', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0] - ->getMarkerBorderColor() - ->setColorProperties('002060', null, ChartColor::EXCEL_COLOR_TYPE_RGB); - -// line details - dashed, smooth line (Bezier) with arrows, 40% transparent -$dataSeriesValues[0] - ->setSmoothLine(true) - ->setScatterLines(true) - ->setLineColorProperties('accent1', 40, ChartColor::EXCEL_COLOR_TYPE_SCHEME); // value, alpha, type -$dataSeriesValues[0]->setLineStyleProperties( - 2.5, // width in points - Properties::LINE_STYLE_COMPOUND_TRIPLE, // compound - Properties::LINE_STYLE_DASH_SQUARE_DOT, // dash - Properties::LINE_STYLE_CAP_SQUARE, // cap - Properties::LINE_STYLE_JOIN_MITER, // join - Properties::LINE_STYLE_ARROW_TYPE_OPEN, // head type - Properties::LINE_STYLE_ARROW_SIZE_4, // head size preset index - Properties::LINE_STYLE_ARROW_TYPE_ARROW, // end type - Properties::LINE_STYLE_ARROW_SIZE_6 // end size preset index -); - -// series 2 - metric2, straight line - no special effects, connected -$dataSeriesValues[1] // square marker border color - ->getMarkerBorderColor() - ->setColorProperties('accent6', 3, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[1] // square marker fill color - ->getMarkerFillColor() - ->setColorProperties('0FFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1] - ->setScatterLines(true) - ->setSmoothLine(false) - ->setLineColorProperties('FF0000', 80, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[1]->setLineWidth(2.0); - -// series 3 - metric3, markers, no line -$dataSeriesValues[2] // triangle? fill - //->setPointMarker('triangle') // let Excel choose shape, which is predicted to be a triangle - ->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[2] // triangle border - ->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[2]->setScatterLines(false); // points not connected -// Added so that Xaxis shows dates instead of Excel-equivalent-year1900-numbers -$xAxis = new ChartAxis(); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601, true); - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Chart'); -$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart1', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - // $yAxis, // yAxis -); - -// Set the position of the chart in the chart sheet -$chart->setTopLeftPosition('A1'); -$chart->setBottomRightPosition('P12'); - -// create a 'Chart' worksheet, add $chart to it -$spreadsheet->createSheet(); -$chartSheet = $spreadsheet->getSheet(1); -$chartSheet->setTitle('Scatter Chart'); - -$chartSheet = $spreadsheet->getSheetByNameOrThrow('Scatter Chart'); -// Add the chart to the worksheet -$chartSheet->addChart($chart); - -/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */ -$helper->renderChart($chart, __FILE__); - -// ------------ Demonstrate Trendlines for metric3 values in a new chart ------------ - -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$D$1', null, 1), -]; -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$9', Properties::FORMAT_CODE_DATE_ISO8601, 8), -]; - -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$D$2:$D$9', Properties::FORMAT_CODE_NUMBER, 4, null, 'triangle', null, 7), -]; - -// add 3 trendlines: -// 1- linear, double-ended arrow, w=0.5, same color as marker fill; nodispRSqr, nodispEq -// 2- polynomial (order=3) no-arrow trendline, w=1.25, same color as marker fill; dispRSqr, dispEq -// 3- moving Avg (period=2) single-arrow trendline, w=1.5, same color as marker fill; no dispRSqr, no dispEq -$trendLines = [ - new TrendLine(TrendLine::TRENDLINE_LINEAR, null, null, false, false), - new TrendLine(TrendLine::TRENDLINE_POLYNOMIAL, 3, null, true, true, 20.0, 28.0, 44104.5, 'metric3 polynomial fit'), - new TrendLine(TrendLine::TRENDLINE_MOVING_AVG, null, 2, true), -]; -$dataSeriesValues[0]->setTrendLines($trendLines); - -// Suppress connecting lines; instead, add different Trendline algorithms to -// determine how well the data fits the algorithm (Rsquared="goodness of fit") -// Display RSqr plus the eqn just because we can. - -$dataSeriesValues[0]->setScatterLines(false); // points not connected -$dataSeriesValues[0]->getMarkerFillColor() - ->setColorProperties('FFFF00', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$dataSeriesValues[0]->getMarkerBorderColor() - ->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); - -// add properties to the trendLines - give each a different color -$dataSeriesValues[0]->getTrendLines()[0]->getLineColor()->setColorProperties('accent4', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[0]->getTrendLines()[0]->setLineStyleProperties(0.5, null, null, null, null, Properties::LINE_STYLE_ARROW_TYPE_STEALTH, 5, Properties::LINE_STYLE_ARROW_TYPE_OPEN, 8); - -$dataSeriesValues[0]->getTrendLines()[1]->getLineColor()->setColorProperties('accent3', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[0]->getTrendLines()[1]->setLineStyleProperties(1.25); - -$dataSeriesValues[0]->getTrendLines()[2]->getLineColor()->setColorProperties('accent2', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); -$dataSeriesValues[0]->getTrendLines()[2]->setLineStyleProperties(1.5, null, null, null, null, null, 0, Properties::LINE_STYLE_ARROW_TYPE_OPEN, 8); - -$xAxis = new ChartAxis(); -$xAxis->setAxisNumberProperties(Properties::FORMAT_CODE_DATE_ISO8601); // m/d/yyyy - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_SMOOTHMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title('Test Scatter Chart - trendlines for metric3 values'); -$yAxisLabel = new Title('Value ($k)'); - -// Create the chart -$chart = new Chart( - 'chart2', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - // $yAxis, // yAxis -); - -// Set the position of the chart in the chart sheet below the first chart -$chart->setTopLeftPosition('A13'); -$chart->setBottomRightPosition('P25'); - -// Add the chart to the worksheet $chartSheet -$chartSheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -$spreadsheet->setActiveSheetIndex(1); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true, resetActiveSheet: false); diff --git a/samples/Chart33b/33_Chart_create_scatter6_value_xaxis.php b/samples/Chart33b/33_Chart_create_scatter6_value_xaxis.php deleted file mode 100644 index c66e0594df..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter6_value_xaxis.php +++ /dev/null @@ -1,134 +0,0 @@ -getActiveSheet(); -$dataSheet->setTitle('Data'); - -$results = [ - ['Station 1', 'Score'], - [13.25, 3], - [16.25, 4], - [18.5, 4], - [15.5, 3], - [15.75, 5], - [17.25, 4], - [10.5, 2], -]; - -$dataSheet->fromArray($results); - -$spreadsheet->createSheet(); - -$chartSheet = $spreadsheet->getSheet(1); -$chartSheet->setTitle('Appendix'); - -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Data!$A$1', null, 1), -]; - -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$A$2:$A$' . count($results), Properties::FORMAT_CODE_NUMBER, 4, null, 'diamond', null, 7), -]; - -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Data!$B$2:$B$' . count($results), Properties::FORMAT_CODE_NUMBER, 8), -]; - -$dataSeriesValues[0]->setScatterLines(false); // Points not connected - -$dataSeriesValues[0]->getMarkerFillColor() - ->setColorProperties('accent1', null, ChartColor::EXCEL_COLOR_TYPE_SCHEME); - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_LINEMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title = new Title($results[0][0]); - -$xAxis = new ChartAxis(); - -$xAxis->setAxisOptionsProperties( - Properties::AXIS_LABELS_NEXT_TO, - null, // horizontalCrossesValue - null, // horizontalCrosses - null, // axisOrientation - null, // majorTmt - Properties::TICK_MARK_OUTSIDE, // minorTmt - '0', // minimum - '6', // maximum - null, // majorUnit - '1', // minorUnit -); - -$xAxis->setAxisType(ChartAxis::AXIS_TYPE_VALUE); - -$yAxis = new ChartAxis(); - -$yAxis->setAxisOptionsProperties( - Properties::AXIS_LABELS_NEXT_TO, - null, // horizontalCrossesValue - null, // horizontalCrosses - null, // axisOrientation - null, // majorTmt - Properties::TICK_MARK_OUTSIDE, // minorTmt - '0', // minimum - '25', // 30 // maximum - null, // majorUnit - '5', // minorUnit -); - -// Create the chart -$chart = new Chart( - 'chart2', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - null, // yAxisLabel - // added xAxis for correct date display - $xAxis, // xAxis - $yAxis, // yAxis -); - -// Set the position of the chart in the chart sheet below the first chart -$chart->setTopLeftPosition('B2'); -$chart->setBottomRightPosition('K22'); - -// Add the chart to the worksheet $chartSheet -$chartSheet->addChart($chart); - -$helper->renderChart($chart, __FILE__); - -$spreadsheet->setActiveSheetIndex(1); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true, resetActiveSheet: false); diff --git a/samples/Chart33b/33_Chart_create_scatter7_blanks.php b/samples/Chart33b/33_Chart_create_scatter7_blanks.php deleted file mode 100644 index d1a8df7b50..0000000000 --- a/samples/Chart33b/33_Chart_create_scatter7_blanks.php +++ /dev/null @@ -1,144 +0,0 @@ -getActiveSheet(); -$worksheet->fromArray( - [ - ['', 2010, 2011, 2012], - ['Q1', 12, 15, 21], - ['Q2', 56, null, 86], - ['Q3', 52, 61, 69], - ['Q4', 30, 32, 0], - ], - strictNullComparison: true -); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), // 2010 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), // 2011 - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), // 2012 -]; -// Set the X-Axis Labels -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$5', null, 4), // Q1 to Q4 -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$5', null, 4), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$5', null, 4), -]; - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_SCATTERCHART, // plotType - null, // plotGrouping (Scatter charts don't have any grouping) - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues, // plotValues - null, // plotDirection - false, // smooth line - DataSeries::STYLE_LINEMARKER // plotStyle -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_TOPRIGHT, null, false); - -$title1 = new Title('Test Scatter Chart Gap'); -$yAxisLabel1 = new Title('Value ($k)'); -// Create the chart -$chart1 = new Chart( - 'chart1', // name - $title1, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel1 // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart1->setTopLeftPosition('A7'); -$chart1->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart1); - -$helper->renderChart($chart1, __FILE__); - -$title2 = new Title('Test Scatter Chart Zero'); -$yAxisLabel2 = new Title('Value ($k)'); -// Create the chart -$chart2 = new Chart( - 'chart2', // name - $title2, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_ZERO, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel2 // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart2->setTopLeftPosition('A22'); -$chart2->setBottomRightPosition('H35'); - -// Add the chart to the worksheet -$worksheet->addChart($chart2); - -$helper->renderChart($chart2, __FILE__); - -$title3 = new Title('Test Scatter Chart Span'); -$yAxisLabel3 = new Title('Value ($k)'); - -// Create the chart -$chart3 = new Chart( - 'chart3', // name - $title3, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_SPAN, // displayBlanksAs - null, // xAxisLabel - $yAxisLabel3 // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart3->setTopLeftPosition('A37'); -$chart3->setBottomRightPosition('H50'); - -// Add the chart to the worksheet -$worksheet->addChart($chart3); - -$helper->renderChart($chart3, __FILE__); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/Chart33b/33_Chart_create_stock2.php b/samples/Chart33b/33_Chart_create_stock2.php deleted file mode 100644 index d8ac5d6983..0000000000 --- a/samples/Chart33b/33_Chart_create_stock2.php +++ /dev/null @@ -1,122 +0,0 @@ -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], - ], - null, - 'A1', - true -); -$worksheet->getStyle('B2:E6')->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_NUMBER_00); - -// Set the Labels for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesLabels = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$B$1', null, 1), //Max / Open - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$C$1', null, 1), //Min / Close - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$D$1', null, 1), //Min Threshold / Min - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$E$1', null, 1), //Max Threshold / Max -]; -// Set the X-Axis Labels -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$xAxisTickValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_STRING, 'Worksheet!$A$2:$A$6', null, 5), // Counts -]; -// Set the Data values for each data series we want to plot -// Datatype -// Cell reference for data -// Format Code -// Number of datapoints in series -// Data values -// Data Marker -$dataSeriesValues = [ - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$B$2:$B$6', null, 5), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$2:$C$6', null, 5), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$D$2:$D$6', null, 5), - new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$E$2:$E$6', null, 5), -]; - -// Build the dataseries -$series = new DataSeries( - DataSeries::TYPE_STOCKCHART, // plotType - null, // plotGrouping - if we set this to not null, then xlsx throws error - range(0, count($dataSeriesValues) - 1), // plotOrder - $dataSeriesLabels, // plotLabel - $xAxisTickValues, // plotCategory - $dataSeriesValues // plotValues -); - -// Set the series in the plot area -$plotArea = new PlotArea(null, [$series]); -// Set the chart legend -$legend = new ChartLegend(ChartLegend::POSITION_RIGHT, null, false); -$legend->getBorderLines()->setLineColorProperties('ffc000', null, ChartColor::EXCEL_COLOR_TYPE_RGB); -$legend->getFillColor()->setColorProperties('cccccc'); -$legendText = new AxisText(); -$legendText->getFillColorObject()->setValue('008080')->setType(ChartColor::EXCEL_COLOR_TYPE_RGB); -$legendText->setShadowProperties(1); -$legend->setLegendText($legendText); - -$title = new Title('Test Stock Chart'); -$xAxisLabel = new Title('Counts'); -$yAxisLabel = new Title('Values'); - -// 3 stmts below are only difference from 33_chart_create_stock.php -$plotArea->setGapWidth(300); -$plotArea->setUseUpBars(true); -$plotArea->setUseDownBars(true); - -// Create the chart -$chart = new Chart( - 'stock-chart', // name - $title, // title - $legend, // legend - $plotArea, // plotArea - true, // plotVisibleOnly - DataSeries::EMPTY_AS_GAP, // displayBlanksAs - $xAxisLabel, // xAxisLabel - $yAxisLabel // yAxisLabel -); - -// Set the position where the chart should appear in the worksheet -$chart->setTopLeftPosition('A7'); -$chart->setBottomRightPosition('H20'); - -// Add the chart to the worksheet -$worksheet->addChart($chart); -$helper->renderChart($chart, __FILE__); -$worksheet->setSelectedCells('G2'); - -// Save Excel 2007 file -$helper->write($spreadsheet, __FILE__, ['Xlsx'], true); diff --git a/samples/ComplexNumbers1/COMPLEX.php b/samples/ComplexNumbers1/COMPLEX.php deleted file mode 100644 index 7cc847d39d..0000000000 --- a/samples/ComplexNumbers1/COMPLEX.php +++ /dev/null @@ -1,41 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [3, 4], - [3, 4, '"j"'], - [3.5, 4.75], - [0, 1], - [1, 0], - [0, -1], - [0, 2], - [2, 0], -]; -$testDataCount = count($testData); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('A' . $row, '=COMPLEX(' . implode(',', $testData[$row - 1]) . ')'); -} - -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(A$row): Formula " - . $worksheet->getCell('A' . $row)->getValueString() - . ' result is ' - . $worksheet->getCell('A' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers1/IMABS.php b/samples/ComplexNumbers1/IMABS.php deleted file mode 100644 index 9a2acb217e..0000000000 --- a/samples/ComplexNumbers1/IMABS.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMABS(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The absolute value of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers1/IMAGINARY.php b/samples/ComplexNumbers1/IMAGINARY.php deleted file mode 100644 index d435db1ae4..0000000000 --- a/samples/ComplexNumbers1/IMAGINARY.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMAGINARY(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The imaginary component of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers1/IMARGUMENT.php b/samples/ComplexNumbers1/IMARGUMENT.php deleted file mode 100644 index 66c9491f02..0000000000 --- a/samples/ComplexNumbers1/IMARGUMENT.php +++ /dev/null @@ -1,49 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMARGUMENT(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Theta Argument of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - . ' radians' - ); -} diff --git a/samples/ComplexNumbers1/IMCONJUGATE.php b/samples/ComplexNumbers1/IMCONJUGATE.php deleted file mode 100644 index 0f7537d4b5..0000000000 --- a/samples/ComplexNumbers1/IMCONJUGATE.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCONJUGATE(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Conjugate value of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers1/IMREAL.php b/samples/ComplexNumbers1/IMREAL.php deleted file mode 100644 index 0c4bb9ce6d..0000000000 --- a/samples/ComplexNumbers1/IMREAL.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMREAL(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The real component of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMCOS.php b/samples/ComplexNumbers2/IMCOS.php deleted file mode 100644 index f7c57c5fff..0000000000 --- a/samples/ComplexNumbers2/IMCOS.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCOS(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Cosine of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMCOSH.php b/samples/ComplexNumbers2/IMCOSH.php deleted file mode 100644 index 3f03cd51c2..0000000000 --- a/samples/ComplexNumbers2/IMCOSH.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCOSH(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Hyperbolic Cosine of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMCOT.php b/samples/ComplexNumbers2/IMCOT.php deleted file mode 100644 index 3c873ca5a1..0000000000 --- a/samples/ComplexNumbers2/IMCOT.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCOT(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Cotangent of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMCSC.php b/samples/ComplexNumbers2/IMCSC.php deleted file mode 100644 index 36b820ceb2..0000000000 --- a/samples/ComplexNumbers2/IMCSC.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCSC(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Cosecant of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMCSCH.php b/samples/ComplexNumbers2/IMCSCH.php deleted file mode 100644 index 4c9cf81b32..0000000000 --- a/samples/ComplexNumbers2/IMCSCH.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMCSCH(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Hyperbolic Cosecant of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMDIV.php b/samples/ComplexNumbers2/IMDIV.php deleted file mode 100644 index 07d73c7efb..0000000000 --- a/samples/ComplexNumbers2/IMDIV.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i', '5-3i'], - ['3+4i', '5+3i'], - ['-238+240i', '10+24i'], - ['1+2i', 30], - ['1+2i', '2i'], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=IMDIV(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Quotient of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMEXP.php b/samples/ComplexNumbers2/IMEXP.php deleted file mode 100644 index e312b378ce..0000000000 --- a/samples/ComplexNumbers2/IMEXP.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMEXP(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Exponential of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMLN.php b/samples/ComplexNumbers2/IMLN.php deleted file mode 100644 index 917cca797a..0000000000 --- a/samples/ComplexNumbers2/IMLN.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMLN(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Natural Logarithm of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMLOG10.php b/samples/ComplexNumbers2/IMLOG10.php deleted file mode 100644 index 57aac04bea..0000000000 --- a/samples/ComplexNumbers2/IMLOG10.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMLOG10(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Base-10 Logarithm of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers2/IMLOG2.php b/samples/ComplexNumbers2/IMLOG2.php deleted file mode 100644 index d35ac2ae40..0000000000 --- a/samples/ComplexNumbers2/IMLOG2.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMLOG2(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Base-2 Logarithm of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMPOWER.php b/samples/ComplexNumbers3/IMPOWER.php deleted file mode 100644 index 12ad32b7b6..0000000000 --- a/samples/ComplexNumbers3/IMPOWER.php +++ /dev/null @@ -1,50 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i', 2], - ['5-12i', 2], - ['3.25+7.5i', 3], - ['3.25-12.5i', 2], - ['-3.25+7.5i', 3], - ['-3.25-7.5i', 4], - ['0-j', 5], - ['0-2.5j', 3], - ['0+j', 2.5], - ['0+1.25j', 2], - [4, 3], - [-2.5, 2], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=IMPOWER(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): " - . $worksheet->getCell('A' . $row)->getValueString() - . ' raised to the power of ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMPRODUCT.php b/samples/ComplexNumbers3/IMPRODUCT.php deleted file mode 100644 index d1ce4dac66..0000000000 --- a/samples/ComplexNumbers3/IMPRODUCT.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i', '5-3i'], - ['3+4i', '5+3i'], - ['-238+240i', '10+24i'], - ['1+2i', 30], - ['1+2i', '2i'], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=IMPRODUCT(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Product of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSEC.php b/samples/ComplexNumbers3/IMSEC.php deleted file mode 100644 index 5f8020ec5c..0000000000 --- a/samples/ComplexNumbers3/IMSEC.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMSEC(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Secant of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSECH.php b/samples/ComplexNumbers3/IMSECH.php deleted file mode 100644 index d25f095070..0000000000 --- a/samples/ComplexNumbers3/IMSECH.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMSECH(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Hyperbolic Ssecant of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSIN.php b/samples/ComplexNumbers3/IMSIN.php deleted file mode 100644 index a883c6b11a..0000000000 --- a/samples/ComplexNumbers3/IMSIN.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMSIN(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Sine of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSINH.php b/samples/ComplexNumbers3/IMSINH.php deleted file mode 100644 index 560c20d881..0000000000 --- a/samples/ComplexNumbers3/IMSINH.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMSINH(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Hyperbolic Sine of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSQRT.php b/samples/ComplexNumbers3/IMSQRT.php deleted file mode 100644 index dff585711e..0000000000 --- a/samples/ComplexNumbers3/IMSQRT.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMSQRT(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Square Root of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSUB.php b/samples/ComplexNumbers3/IMSUB.php deleted file mode 100644 index c6576488a9..0000000000 --- a/samples/ComplexNumbers3/IMSUB.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i', '5-3i'], - ['3+4i', '5+3i'], - ['-238+240i', '10+24i'], - ['1+2i', 30], - ['1+2i', '2i'], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=IMSUB(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Difference between " - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMSUM.php b/samples/ComplexNumbers3/IMSUM.php deleted file mode 100644 index be818680fe..0000000000 --- a/samples/ComplexNumbers3/IMSUM.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i', '5-3i'], - ['3+4i', '5+3i'], - ['-238+240i', '10+24i'], - ['1+2i', 30], - ['1+2i', '2i'], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=IMSUM(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Sum of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ComplexNumbers3/IMTAN.php b/samples/ComplexNumbers3/IMTAN.php deleted file mode 100644 index e9541d0cc5..0000000000 --- a/samples/ComplexNumbers3/IMTAN.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - ['3+4i'], - ['5-12i'], - ['3.25+7.5i'], - ['3.25-12.5i'], - ['-3.25+7.5i'], - ['-3.25-7.5i'], - ['0-j'], - ['0-2.5j'], - ['0+j'], - ['0+1.25j'], - [4], - [-2.5], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('B' . $row, '=IMTAN(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): The Tangent of " - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('B' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/ConditionalFormatting/01_Basic_Comparisons.php b/samples/ConditionalFormatting/01_Basic_Comparisons.php deleted file mode 100644 index 30359bc564..0000000000 --- a/samples/ConditionalFormatting/01_Basic_Comparisons.php +++ /dev/null @@ -1,215 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Literal Value Comparison') - ->setCellValue('A9', 'Value Comparison with Absolute Cell Reference $H$9') - ->setCellValue('A17', 'Value Comparison with Relative Cell References') - ->setCellValue('A23', 'Value Comparison with Formula based on AVERAGE() ± STDEV()') - ->setCellValue('A30', 'Literal String Value Comparison'); - -$dataArray = [ - [-2, -1, 0, 1, 2], - [-1, 0, 1, 2, 3], - [0, 1, 2, 3, 4], - [1, 2, 3, 4, 5], -]; - -$betweenDataArray = [ - [2, 7, 6], - [9, 5, 1], - [4, 3, 8], -]; - -$stringArray = [ - ['I'], - ['Love'], - ['PHP'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true) - ->fromArray($dataArray, null, 'A10', true) - ->fromArray($betweenDataArray, null, 'A18', true) - ->fromArray($dataArray, null, 'A24', true) - ->fromArray($stringArray, null, 'A31', true) - ->setCellValue('H9', 1); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:E1')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A9:E9')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A17:E17')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A23:E23')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A30:E30')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$yellowStyle = new Style(false, true); -$yellowStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_YELLOW); -$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE)); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); -$redStyle = new Style(false, true); -$redStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_RED); -$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Literal Value Comparison -$cellRange = 'A2:E5'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals(0) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->greaterThan(0) - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->lessThan(0) - ->setStyle($redStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Comparison with Absolute Cell Reference $H$9 -$cellRange = 'A10:E13'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals('$H$9', Wizard::VALUE_TYPE_CELL) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->greaterThan('$H$9', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->lessThan('$H$9', Wizard::VALUE_TYPE_CELL) - ->setStyle($redStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Comparison with Relative Cell References -$cellRange = 'A18:A20'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->between('$B1', Wizard::VALUE_TYPE_CELL) - ->and('$C1', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Comparison with Formula -$cellRange = 'A24:E27'; -// accommodation for phpstan -$absoluteCoordinate = fn (mixed $cell): string => is_string($cell) ? Coordinate::absoluteCoordinate($cell) : ''; -$formulaRange = implode( - ':', - array_map( - $absoluteCoordinate, - Coordinate::splitRange($cellRange)[0] - ) -); -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->between('AVERAGE(' . $formulaRange . ')-STDEV(' . $formulaRange . ')', Wizard::VALUE_TYPE_FORMULA) - ->and('AVERAGE(' . $formulaRange . ')+STDEV(' . $formulaRange . ')', Wizard::VALUE_TYPE_FORMULA) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->greaterThan('AVERAGE(' . $formulaRange . ')+STDEV(' . $formulaRange . ')', Wizard::VALUE_TYPE_FORMULA) - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->lessThan('AVERAGE(' . $formulaRange . ')-STDEV(' . $formulaRange . ')', Wizard::VALUE_TYPE_FORMULA) - ->setStyle($redStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Comparison with String Literal -$cellRange = 'A31:A33'; -$formulaRange = implode( - ':', - array_map( - $absoluteCoordinate, - Coordinate::splitRange($cellRange)[0] - ) -); -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals('LOVE') - ->setStyle($redStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$cellWizard->equals('PHP') - ->setStyle($greenStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/02_Text_Comparisons.php b/samples/ConditionalFormatting/02_Text_Comparisons.php deleted file mode 100644 index 2df349e8e2..0000000000 --- a/samples/ConditionalFormatting/02_Text_Comparisons.php +++ /dev/null @@ -1,231 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Value Begins With Literal') - ->setCellValue('A7', 'Value Ends With Literal') - ->setCellValue('A13', 'Value Contains Literal') - ->setCellValue('A19', "Value Doesn't Contain Literal") - ->setCellValue('E1', 'Value Begins With using Cell Reference') - ->setCellValue('E7', 'Value Ends With using Cell Reference') - ->setCellValue('E13', 'Value Contains using Cell Reference') - ->setCellValue('E19', "Value Doesn't Contain using Cell Reference") - ->setCellValue('A25', 'Simple Comparison using Concatenation Formula'); - -$dataArray = [ - ['HELLO', 'WORLD'], - ['MELLOW', 'YELLOW'], - ['SLEEPY', 'HOLLOW'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true) - ->fromArray($dataArray, null, 'A8', true) - ->fromArray($dataArray, null, 'A14', true) - ->fromArray($dataArray, null, 'A20', true) - ->fromArray($dataArray, null, 'E2', true) - ->fromArray($dataArray, null, 'E8', true) - ->fromArray($dataArray, null, 'E14', true) - ->fromArray($dataArray, null, 'E20', true) - ->fromArray($dataArray, null, 'A26', true) - ->setCellValue('D1', 'H') - ->setCellValue('D7', 'OW') - ->setCellValue('D13', 'LL') - ->setCellValue('D19', 'EL') - ->setCellValue('C26', 'HELLO WORLD') - ->setCellValue('C27', 'SOYLENT GREEN') - ->setCellValue('C28', 'SLEEPY HOLLOW'); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:G1')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A7:G7')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A13:G13')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A19:G19')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A25:C25')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$yellowStyle = new Style(false, true); -$yellowStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_YELLOW); -$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE)); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); -$redStyle = new Style(false, true); -$redStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_RED); -$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Literal Value Begins With -$cellRange = 'A2:B4'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->beginsWith('H') - ->setStyle($yellowStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Begins With using Cell Reference -$cellRange = 'E2:F4'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->beginsWith('$D$1', Wizard::VALUE_TYPE_CELL) - ->setStyle($yellowStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Literal Value Ends With -$cellRange = 'A8:B10'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->endsWith('OW') - ->setStyle($yellowStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Ends With using Cell Reference -$cellRange = 'E8:F10'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->endsWith('$D$7', Wizard::VALUE_TYPE_CELL) - ->setStyle($yellowStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Literal Value Contains -$cellRange = 'A14:B16'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->contains('LL') - ->setStyle($greenStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Contains using Cell Reference -$cellRange = 'E14:F16'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->contains('$D$13', Wizard::VALUE_TYPE_CELL) - ->setStyle($greenStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Literal Value Does Not Contain -$cellRange = 'A20:B22'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->doesNotContain('EL') - ->setStyle($redStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Value Contains using Cell Reference -$cellRange = 'E20:F22'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\TextValue $textWizard */ -$textWizard = $wizardFactory->newRule(Wizard::TEXT_VALUE); - -$textWizard->doesNotContain('$D$19', Wizard::VALUE_TYPE_CELL) - ->setStyle($redStyle); -$conditionalStyles[] = $textWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($textWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Simple Comparison using Concatenation Formula -$cellRange = 'C26:C28'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\CellValue $cellWizard */ -$cellWizard = $wizardFactory->newRule(Wizard::CELL_VALUE); - -$cellWizard->equals('CONCATENATE($A1," ",$B1)', Wizard::VALUE_TYPE_FORMULA) - ->setStyle($yellowStyle); -$conditionalStyles[] = $cellWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($cellWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -$spreadsheet->getActiveSheet()->getColumnDimension('C')->setAutoSize(true); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/03_Blank_Comparisons.php b/samples/ConditionalFormatting/03_Blank_Comparisons.php deleted file mode 100644 index a64b1cbcd1..0000000000 --- a/samples/ConditionalFormatting/03_Blank_Comparisons.php +++ /dev/null @@ -1,79 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Blank Comparison'); - -$dataArray = [ - ['HELLO', null], - [null, 'WORLD'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:B1')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); -$redStyle = new Style(false, true); -$redStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_RED); -$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Blank Comparison -$cellRange = 'A2:B3'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Blanks $blanksWizard */ -$blanksWizard = $wizardFactory->newRule(Wizard::BLANKS); - -$blanksWizard->setStyle($redStyle); -$conditionalStyles[] = $blanksWizard->getConditional(); - -$blanksWizard->notBlank() - ->setStyle($greenStyle); -$conditionalStyles[] = $blanksWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($blanksWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/04_Error_Comparisons.php b/samples/ConditionalFormatting/04_Error_Comparisons.php deleted file mode 100644 index 4b8770280e..0000000000 --- a/samples/ConditionalFormatting/04_Error_Comparisons.php +++ /dev/null @@ -1,82 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Error Comparison'); - -$dataArray = [ - [5, -2, '=A2/B2'], - [5, -1, '=A3/B3'], - [5, 0, '=A4/B4'], - [5, 1, '=A5/B5'], - [5, 2, '=A6/B6'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:C1')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); -$redStyle = new Style(false, true); -$redStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_RED); -$redStyle->getFont()->setColor(new Color(Color::COLOR_GREEN)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Blank Comparison -$cellRange = 'C2:C6'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Errors $errorsWizard */ -$errorsWizard = $wizardFactory->newRule(Wizard::ERRORS); - -$errorsWizard->setStyle($redStyle); -$conditionalStyles[] = $errorsWizard->getConditional(); - -$errorsWizard->notError() - ->setStyle($greenStyle); -$conditionalStyles[] = $errorsWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($errorsWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/05_Date_Comparisons.php b/samples/ConditionalFormatting/05_Date_Comparisons.php deleted file mode 100644 index d7dc3bee80..0000000000 --- a/samples/ConditionalFormatting/05_Date_Comparisons.php +++ /dev/null @@ -1,155 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); - -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('B1', 'yesterday()') - ->setCellValue('C1', 'today()') - ->setCellValue('D1', 'tomorrow()') - ->setCellValue('E1', 'last7Days()') - ->setCellValue('F1', 'lastWeek()') - ->setCellValue('G1', 'thisWeek()') - ->setCellValue('H1', 'nextWeek()') - ->setCellValue('I1', 'lastMonth()') - ->setCellValue('J1', 'thisMonth()') - ->setCellValue('K1', 'nextMonth()'); - -$dateFunctionArray = [ - 'yesterday()', - 'today()', - 'tomorrow()', - 'last7Days()', - 'lastWeek()', - 'thisWeek()', - 'nextWeek()', - 'lastMonth()', - 'thisMonth()', - 'nextMonth()', -]; -$dateTitleArray = [ - ['First day of last month'], - ['Last day of last month'], - ['Last Monday'], - ['Last Friday'], - ['Monday last week'], - ['Wednesday last week'], - ['Friday last week'], - ['Yesterday'], - ['Today'], - ['Tomorrow'], - ['Monday this week'], - ['Wednesday this week'], - ['Friday this week'], - ['Monday next week'], - ['Wednesday next week'], - ['Friday next week'], - ['First day of next month'], - ['Last day of next month'], -]; -$dataArray = [ - ['=EOMONTH(TODAY(),-2)+1'], - ['=EOMONTH(TODAY(),-1)'], - ['=TODAY()-WEEKDAY(TODAY(),3)'], - ['=TODAY()-WEEKDAY(TODAY())-1'], - ['=2-WEEKDAY(TODAY())+TODAY()-7'], - ['=4-WEEKDAY(TODAY())+TODAY()-7'], - ['=6-WEEKDAY(TODAY())+TODAY()-7'], - ['=TODAY()-1'], - ['=TODAY()'], - ['=TODAY()+1'], - ['=2-WEEKDAY(TODAY())+TODAY()'], - ['=4-WEEKDAY(TODAY())+TODAY()'], - ['=6-WEEKDAY(TODAY())+TODAY()'], - ['=2-WEEKDAY(TODAY())+TODAY()+7'], - ['=4-WEEKDAY(TODAY())+TODAY()+7'], - ['=6-WEEKDAY(TODAY())+TODAY()+7'], - ['=EOMONTH(TODAY(),0)+1'], - ['=EOMONTH(TODAY(),1)'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dateFunctionArray, null, 'B1', true); -$spreadsheet->getActiveSheet() - ->fromArray($dateTitleArray, null, 'A2', true); -for ($column = 'B'; $column !== 'L'; ++$column) { - $spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, "{$column}2", true); -} - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('B1:K1')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('B1:K1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$yellowStyle = new Style(false, true); -$yellowStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_YELLOW); -$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); -for ($column = 'B'; $column !== 'L'; ++$column) { - $wizardFactory = new Wizard("{$column}2:{$column}19"); - /** @var Wizard\DateValue $dateWizard */ - $dateWizard = $wizardFactory->newRule(Wizard::DATES_OCCURRING); - $conditionalStyles = []; - - /** @var string */ - $cellContents = $spreadsheet->getActiveSheet()->getCell("{$column}1")->getValue(); - $methodName = trim($cellContents, '()'); - /** @var Wizard\DateValue */ - $targetStyle = $dateWizard->$methodName(); - $targetStyle->setStyle($yellowStyle); - - $conditionalStyles[] = $dateWizard->getConditional(); - - $spreadsheet->getActiveSheet() - ->getStyle($dateWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); -} - -// Set conditional formatting rules and styles -$helper->log('Set some additional styling for date formats'); - -$spreadsheet->getActiveSheet()->getStyle('B:B')->getNumberFormat()->setFormatCode('ddd dd-mmm-yyyy'); -for ($column = 'A'; $column !== 'L'; ++$column) { - if ($column !== 'A') { - $spreadsheet->getActiveSheet()->getStyle("{$column}:{$column}") - ->getNumberFormat()->setFormatCode('ddd dd-mmm-yyyy'); - } - $spreadsheet->getActiveSheet()->getColumnDimension($column) - ->setAutoSize(true); -} -$spreadsheet->getActiveSheet()->getStyle('A:A')->getFont()->setBold(true); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/06_Duplicate_Comparisons.php b/samples/ConditionalFormatting/06_Duplicate_Comparisons.php deleted file mode 100644 index cf79c888f7..0000000000 --- a/samples/ConditionalFormatting/06_Duplicate_Comparisons.php +++ /dev/null @@ -1,88 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Duplicates Comparison'); - -$dataArray = [ - [1, 0, 3], - [2, 1, 1], - [3, 1, 4], - [4, 2, 1], - [5, 3, 5], - [6, 5, 9], - [7, 8, 2], - [8, 13, 6], - [9, 21, 5], - [10, 34, 3], - [11, 55, 5], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:C1')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$yellowStyle = new Style(false, true); -$yellowStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_YELLOW); -$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE)); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Duplicates Comparison -$cellRange = 'A2:C12'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Duplicates $duplicatesWizard */ -$duplicatesWizard = $wizardFactory->newRule(Wizard::DUPLICATES); - -$duplicatesWizard->setStyle($yellowStyle); -$conditionalStyles[] = $duplicatesWizard->getConditional(); - -$duplicatesWizard->unique() - ->setStyle($greenStyle); -$conditionalStyles[] = $duplicatesWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($duplicatesWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/07_Expression_Comparisons.php b/samples/ConditionalFormatting/07_Expression_Comparisons.php deleted file mode 100644 index 109082ab28..0000000000 --- a/samples/ConditionalFormatting/07_Expression_Comparisons.php +++ /dev/null @@ -1,151 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Mark Baker') - ->setLastModifiedBy('Mark Baker') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$spreadsheet->setActiveSheetIndex(0); -$spreadsheet->getActiveSheet() - ->setCellValue('A1', 'Odd/Even Expression Comparison') - ->setCellValue('A4', 'Note that these functions are not available for Xls files') - ->setCellValue('A15', 'Sales Grid Expression Comparison') - ->setCellValue('A25', 'Sales Grid Multiple Expression Comparison'); - -$dataArray = [ - [1, 0, 3], - [2, 1, 1], - [3, 1, 4], - [4, 2, 1], - [5, 3, 5], - [6, 5, 9], - [7, 8, 2], - [8, 13, 6], - [9, 21, 5], - [10, 34, 4], -]; - -$salesGrid = [ - ['Name', 'Sales', 'Country', 'Quarter'], - ['Smith', 16753, 'UK', 'Q3'], - ['Johnson', 14808, 'USA', 'Q4'], - ['Williams', 10644, 'UK', 'Q2'], - ['Jones', 1390, 'USA', 'Q3'], - ['Brown', 4865, 'USA', 'Q4'], - ['Williams', 12438, 'UK', 'Q2'], -]; - -$spreadsheet->getActiveSheet() - ->fromArray($dataArray, null, 'A2', true); -$spreadsheet->getActiveSheet() - ->fromArray($salesGrid, null, 'A16', true); -$spreadsheet->getActiveSheet() - ->fromArray($salesGrid, null, 'A26', true); - -// Set title row bold -$helper->log('Set title row bold'); -$spreadsheet->getActiveSheet()->getStyle('A1:B1')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A15:D16')->getFont()->setBold(true); -$spreadsheet->getActiveSheet()->getStyle('A25:D26')->getFont()->setBold(true); - -// Define some styles for our Conditionals -$helper->log('Define some styles for our Conditionals'); -$yellowStyle = new Style(false, true); -$yellowStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_YELLOW); -$yellowStyle->getFont()->setColor(new Color(Color::COLOR_BLUE)); -$greenStyle = new Style(false, true); -$greenStyle->getFill() - ->setFillType(Fill::FILL_SOLID) - ->getStartColor()->setARGB(Color::COLOR_GREEN); -$greenStyle->getFont()->setColor(new Color(Color::COLOR_DARKRED)); - -$greenStyleMoney = clone $greenStyle; -$greenStyleMoney->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting and set styles'); - -// Set rules for Odd/Even Expression Comparison -$cellRange = 'A2:C11'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Expression $expressionWizard */ -$expressionWizard = $wizardFactory->newRule(Wizard::EXPRESSION); - -$expressionWizard->expression('ISODD(A1)') - ->setStyle($greenStyle); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$expressionWizard->expression('ISEVEN(A1)') - ->setStyle($yellowStyle); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($expressionWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Sales Grid Row match against Country Comparison -$cellRange = 'A17:D22'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Expression $expressionWizard */ -$expressionWizard = $wizardFactory->newRule(Wizard::EXPRESSION); - -$expressionWizard->expression('$C1="USA"') - ->setStyle($greenStyleMoney); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($expressionWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set rules for Sales Grid Row match against Country and Quarter Comparison -$cellRange = 'A27:D32'; -$conditionalStyles = []; -$wizardFactory = new Wizard($cellRange); -/** @var Wizard\Expression $expressionWizard */ -$expressionWizard = $wizardFactory->newRule(Wizard::EXPRESSION); - -$expressionWizard->expression('AND($C1="USA",$D1="Q4")') - ->setStyle($greenStyleMoney); -$conditionalStyles[] = $expressionWizard->getConditional(); - -$spreadsheet->getActiveSheet() - ->getStyle($expressionWizard->getCellRange()) - ->setConditionalStyles($conditionalStyles); - -// Set conditional formatting rules and styles -$helper->log('Set some additional styling for money formats'); - -$spreadsheet->getActiveSheet()->getStyle('B17:B22') - ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD); -$spreadsheet->getActiveSheet()->getStyle('B27:B32') - ->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_ACCOUNTING_USD); -$spreadsheet->getActiveSheet()->getColumnDimension('B') - ->setAutoSize(true); - -// Save -$helper->write($spreadsheet, __FILE__); diff --git a/samples/ConditionalFormatting/cond08_colorscale.php b/samples/ConditionalFormatting/cond08_colorscale.php deleted file mode 100644 index 839479bea6..0000000000 --- a/samples/ConditionalFormatting/cond08_colorscale.php +++ /dev/null @@ -1,65 +0,0 @@ -log('Create new Spreadsheet object'); -$spreadsheet = new Spreadsheet(); -$sheet = $spreadsheet->getActiveSheet(); - -// Set document properties -$helper->log('Set document properties'); -$spreadsheet->getProperties()->setCreator('Owen Leibman') - ->setLastModifiedBy('Owen Leibman') - ->setTitle('PhpSpreadsheet Test Document') - ->setSubject('PhpSpreadsheet Test Document') - ->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.') - ->setKeywords('office PhpSpreadsheet php') - ->setCategory('Test result file'); - -// Create the worksheet -$helper->log('Add data'); -$sheet - ->setCellValue('A1', 1) - ->setCellValue('A2', 2) - ->setCellValue('A3', 8) - ->setCellValue('A4', 4) - ->setCellValue('A5', 5) - ->setCellValue('A6', 6) - ->setCellValue('A7', 7) - ->setCellValue('A8', 3) - ->setCellValue('A9', 9) - ->setCellValue('A10', 10); - -// Set conditional formatting rules and styles -$helper->log('Define conditional formatting using Color Scales'); - -$cellRange = 'A1:A10'; -$condition1 = new Conditional(); -$condition1->setConditionType(Conditional::CONDITION_COLORSCALE); -$colorScale = new ConditionalColorScale(); -$condition1->setColorScale($colorScale); -$colorScale - ->setMinimumConditionalFormatValueObject(new ConditionalFormatValueObject('min')) - ->setMidpointConditionalFormatValueObject(new ConditionalFormatValueObject('percentile', '40')) - ->setMaximumConditionalFormatValueObject(new ConditionalFormatValueObject('max')) - ->setMinimumColor(new Color('FFF8696B')) - ->setMidpointColor(new Color('FFFFEB84')) - ->setMaximumColor(new Color('FF63BE7B')); - -$conditionalStyles = [$condition1]; - -$sheet - ->getStyle($cellRange) - ->setConditionalStyles($conditionalStyles); -$sheet->setSelectedCells('B1'); - -// Save -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/Database/DAVERAGE.php b/samples/Database/DAVERAGE.php deleted file mode 100644 index 0416dd3a2b..0000000000 --- a/samples/Database/DAVERAGE.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The Average yield of Apple trees over 10\' in height'); -$worksheet->setCellValue('B12', '=DAVERAGE(A4:E10,"Yield",A1:B2)'); - -$worksheet->setCellValue('A13', 'The Average age of all Apple and Pear trees in the orchard'); -$worksheet->setCellValue('B13', '=DAVERAGE(A4:E10,3,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:B2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DCOUNT.php b/samples/Database/DCOUNT.php deleted file mode 100644 index 476e365deb..0000000000 --- a/samples/Database/DCOUNT.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 'N/A', 10, 75.00], - ['Pear', 9, 8, 8, 77.00], - ['Apple', 12, 11, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The Number of Apple trees between 10\' and 16\' in height whose age is known'); -$worksheet->setCellValue('B12', '=DCOUNT(A4:E10,"Age",A1:F2)'); - -$worksheet->setCellValue('A13', 'The Number of Apple and Pear trees in the orchard with a numeric value in column 3 ("Age")'); -$worksheet->setCellValue('B13', '=DCOUNT(A4:E10,3,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:F2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DCOUNTA.php b/samples/Database/DCOUNTA.php deleted file mode 100644 index ecee4206c4..0000000000 --- a/samples/Database/DCOUNTA.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 'N/A', 10, 75.00], - ['Pear', 9, 8, 8, 77.00], - ['Apple', 12, 11, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The Number of Apple trees between 10\' and 16\' in height'); -$worksheet->setCellValue('B12', '=DCOUNTA(A4:E10,"Age",A1:F2)'); - -$worksheet->setCellValue('A13', 'The Number of Apple and Pear trees in the orchard'); -$worksheet->setCellValue('B13', '=DCOUNTA(A4:E10,3,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:F2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DGET.php b/samples/Database/DGET.php deleted file mode 100644 index cfe650961e..0000000000 --- a/samples/Database/DGET.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', '>12', null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The height of the Apple tree between 10\' and 16\' tall'); -$worksheet->setCellValue('B12', '=DGET(A4:E10,"Height",A1:F2)'); - -$worksheet->setCellValue('A13', 'The height of the Apple tree (will return an Excel error, because there is more than one apple tree)'); -$worksheet->setCellValue('B13', '=DGET(A4:E10,"Height",A1:A2)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:F2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DMAX.php b/samples/Database/DMAX.php deleted file mode 100644 index fbb6b906a4..0000000000 --- a/samples/Database/DMAX.php +++ /dev/null @@ -1,57 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The tallest tree in the orchard'); -$worksheet->setCellValue('B12', '=DMAX(A4:E10,"Height",A4:E10)'); - -$worksheet->setCellValue('A13', 'The Oldest apple tree in the orchard'); -$worksheet->setCellValue('B13', '=DMAX(A4:E10,3,A1:A2)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$helper->log('ALL'); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DMIN.php b/samples/Database/DMIN.php deleted file mode 100644 index 565c9501ad..0000000000 --- a/samples/Database/DMIN.php +++ /dev/null @@ -1,57 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The shortest tree in the orchard'); -$worksheet->setCellValue('B12', '=DMIN(A4:E10,"Height",A4:E10)'); - -$worksheet->setCellValue('A13', 'The Youngest apple tree in the orchard'); -$worksheet->setCellValue('B13', '=DMIN(A4:E10,3,A1:A2)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$helper->log('ALL'); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DPRODUCT.php b/samples/Database/DPRODUCT.php deleted file mode 100644 index d9cf469303..0000000000 --- a/samples/Database/DPRODUCT.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 77.00], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The product of the yields of all Apple trees over 10\' in the orchard'); -$worksheet->setCellValue('B12', '=DPRODUCT(A4:E10,"Yield",A1:B2)'); - -$worksheet->setCellValue('A13', 'The product of the yields of all Apple trees in the orchard'); -$worksheet->setCellValue('B13', '=DPRODUCT(A4:E10,"Yield",A1:A2)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:B2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DSTDEV.php b/samples/Database/DSTDEV.php deleted file mode 100644 index b8e23b6e27..0000000000 --- a/samples/Database/DSTDEV.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The estimated standard deviation in the yield of Apple and Pear trees'); -$worksheet->setCellValue('B12', '=DSTDEV(A4:E10,"Yield",A1:A3)'); - -$worksheet->setCellValue('A13', 'The estimated standard deviation in height of Apple and Pear trees'); -$worksheet->setCellValue('B13', '=DSTDEV(A4:E10,2,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DSTDEVP.php b/samples/Database/DSTDEVP.php deleted file mode 100644 index 0e20ce8007..0000000000 --- a/samples/Database/DSTDEVP.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The standard deviation in the yield of Apple and Pear trees'); -$worksheet->setCellValue('B12', '=DSTDEVP(A4:E10,"Yield",A1:A3)'); - -$worksheet->setCellValue('A13', 'The standard deviation in height of Apple and Pear trees'); -$worksheet->setCellValue('B13', '=DSTDEVP(A4:E10,2,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DSUM.php b/samples/Database/DSUM.php deleted file mode 100644 index 2a88008a52..0000000000 --- a/samples/Database/DSUM.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The total profit from apple trees'); -$worksheet->setCellValue('B12', '=DSUM(A4:E10,"Profit",A1:A2)'); - -$worksheet->setCellValue('A13', 'Total profit from apple trees with a height between 10 and 16 feet, and all pear trees'); -$worksheet->setCellValue('B13', '=DSUM(A4:E10,"Profit",A1:F3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A2', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:F3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DVAR.php b/samples/Database/DVAR.php deleted file mode 100644 index 69809cc170..0000000000 --- a/samples/Database/DVAR.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The estimated variance in the yield of Apple and Pear trees'); -$worksheet->setCellValue('B12', '=DVAR(A4:E10,"Yield",A1:A3)'); - -$worksheet->setCellValue('A13', 'The estimated variance in height of Apple and Pear trees'); -$worksheet->setCellValue('B13', '=DVAR(A4:E10,2,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/Database/DVARP.php b/samples/Database/DVARP.php deleted file mode 100644 index d362a82007..0000000000 --- a/samples/Database/DVARP.php +++ /dev/null @@ -1,58 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$database = [['Tree', 'Height', 'Age', 'Yield', 'Profit'], - ['Apple', 18, 20, 14, 105.00], - ['Pear', 12, 12, 10, 96.00], - ['Cherry', 13, 14, 9, 105.00], - ['Apple', 14, 15, 10, 75.00], - ['Pear', 9, 8, 8, 76.80], - ['Apple', 8, 9, 6, 45.00], -]; -$criteria = [['Tree', 'Height', 'Age', 'Yield', 'Profit', 'Height'], - ['="=Apple"', '>10', null, null, null, '<16'], - ['="=Pear"', null, null, null, null, null], -]; - -$worksheet->fromArray($criteria, null, 'A1'); -$worksheet->fromArray($database, null, 'A4'); - -$worksheet->setCellValue('A12', 'The variance in the yield of Apple and Pear trees'); -$worksheet->setCellValue('B12', '=DVARP(A4:E10,"Yield",A1:A3)'); - -$worksheet->setCellValue('A13', 'The variance in height of Apple and Pear trees'); -$worksheet->setCellValue('B13', '=DVARP(A4:E10,2,A1:A3)'); - -$helper->log('Database'); - -$databaseData = $worksheet->rangeToArray('A4:E10', null, true, true, true); -$helper->displayGrid($databaseData); - -// Test the formulae -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B12', 'A12'); - -$helper->log('Criteria'); - -$criteriaData = $worksheet->rangeToArray('A1:A3', null, true, true, true); -$helper->displayGrid($criteriaData); - -$helper->logCalculationResult($worksheet, $functionName, 'B13', 'A13'); diff --git a/samples/DateTime/DATE.php b/samples/DateTime/DATE.php deleted file mode 100644 index d4c1d0cba0..0000000000 --- a/samples/DateTime/DATE.php +++ /dev/null @@ -1,45 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [[2012, 3, 26], [2012, 2, 29], [2012, 4, 1], [2012, 12, 25], - [2012, 10, 31], [2012, 11, 5], [2012, 1, 1], [2012, 3, 17], - [2011, 2, 29], [7, 5, 3], [2012, 13, 1], [2012, 11, 45], - [2012, 0, 0], [2012, 1, 0], [2012, 0, 1], - [2012, -2, 2], [2012, 2, -2], [2012, -2, -2], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log("(A{$row}) Year: " . $worksheet->getCell('A' . $row)->getFormattedValue()); - $helper->log("(B{$row}) Month: " . $worksheet->getCell('B' . $row)->getFormattedValue()); - $helper->log("(C{$row}) Day: " . $worksheet->getCell('C' . $row)->getFormattedValue()); - $helper->log('Formula: ' . $worksheet->getCell('D' . $row)->getValueString()); - $helper->log('Excel DateStamp: ' . $worksheet->getCell('D' . $row)->getCalculatedValueString()); - $helper->log('Formatted DateStamp: ' . $worksheet->getCell('E' . $row)->getFormattedValue()); - $helper->log(''); -} diff --git a/samples/DateTime/DATEDIF.php b/samples/DateTime/DATEDIF.php deleted file mode 100644 index ca9f249de4..0000000000 --- a/samples/DateTime/DATEDIF.php +++ /dev/null @@ -1,61 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 1, 1], - [1936, 3, 17], - [1960, 12, 19], - [1999, 12, 31], - [2000, 1, 1], - [2019, 2, 14], - [2020, 7, 4], - [2020, 2, 29], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=TODAY()'); - $worksheet->setCellValue('G' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "Y")'); - $worksheet->setCellValue('H' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "M")'); - $worksheet->setCellValue('I' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "D")'); - $worksheet->setCellValue('J' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "MD")'); - $worksheet->setCellValue('K' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "YM")'); - $worksheet->setCellValue('L' . $row, '=DATEDIF(D' . $row . ', F' . $row . ', "YD")'); -} -$worksheet->getStyle('E1:F' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf( - 'Between: %s and %s', - $worksheet->getCell('E' . $row)->getFormattedValue(), - $worksheet->getCell('F' . $row)->getFormattedValue() - )); - $helper->log('In years ("Y"): ' . $worksheet->getCell('G' . $row)->getCalculatedValueString()); - $helper->log('In months ("M"): ' . $worksheet->getCell('H' . $row)->getCalculatedValueString()); - $helper->log('In days ("D"): ' . $worksheet->getCell('I' . $row)->getCalculatedValueString()); - $helper->log('In days ignoring months and years ("MD"): ' . $worksheet->getCell('J' . $row)->getCalculatedValueString()); - $helper->log('In months ignoring days and years ("YM"): ' . $worksheet->getCell('K' . $row)->getCalculatedValueString()); - $helper->log('In days ignoring years ("YD"): ' . $worksheet->getCell('L' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/DATEVALUE.php b/samples/DateTime/DATEVALUE.php deleted file mode 100644 index f8a52fe3ad..0000000000 --- a/samples/DateTime/DATEVALUE.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = ['26 March 2012', '29 Feb 2012', 'April 1, 2012', '25/12/2012', - '2012-Oct-31', '5th November', 'January 1st', 'April 2012', - '17-03', '03-17', '03-2012', '29 Feb 2011', '03-05-07', - '03-MAY-07', '03-13-07', '13-03-07', '03/13/07', '13/03/07', -]; -$testDateCount = count($testDates); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('A' . $row, $testDates[$row - 1]); - $worksheet->setCellValue('B' . $row, '=DATEVALUE(A' . $row . ')'); - $worksheet->setCellValue('C' . $row, '=B' . $row); -} - -$worksheet->getStyle('C1:C' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -$helper->log('Warning: The PhpSpreadsheet DATEVALUE() function accepts a wider range of date formats than MS Excel DATEFORMAT() function.'); -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log("(A{$row}) Date String: " . $worksheet->getCell('A' . $row)->getFormattedValue()); - $helper->log('Formula: ' . $worksheet->getCell('B' . $row)->getValueString()); - $helper->log('Excel DateStamp: ' . $worksheet->getCell('B' . $row)->getCalculatedValueString()); - $helper->log('Formatted DateStamp: ' . $worksheet->getCell('C' . $row)->getFormattedValue()); - $helper->log(''); -} diff --git a/samples/DateTime/DAY.php b/samples/DateTime/DAY.php deleted file mode 100644 index 4e14e32a2a..0000000000 --- a/samples/DateTime/DAY.php +++ /dev/null @@ -1,50 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=DAY(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Day is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/DAYS.php b/samples/DateTime/DAYS.php deleted file mode 100644 index 106ec450fa..0000000000 --- a/samples/DateTime/DAYS.php +++ /dev/null @@ -1,53 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 1, 1], - [1936, 3, 17], - [1960, 12, 19], - [1999, 12, 31], - [2000, 1, 1], - [2019, 2, 14], - [2020, 7, 4], - [2020, 2, 29], - [2029, 12, 31], - [2525, 1, 1], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=TODAY()'); - $worksheet->setCellValue('G' . $row, '=DAYS(D' . $row . ', F' . $row . ')'); -} -$worksheet->getStyle('E1:F' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf( - 'Between: %s and %s', - $worksheet->getCell('E' . $row)->getFormattedValue(), - $worksheet->getCell('F' . $row)->getFormattedValue() - )); - $helper->log('Days: ' . $worksheet->getCell('G' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/DAYS360.php b/samples/DateTime/DAYS360.php deleted file mode 100644 index 557e824629..0000000000 --- a/samples/DateTime/DAYS360.php +++ /dev/null @@ -1,59 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 1, 1], - [1936, 3, 17], - [1960, 12, 19], - [1999, 12, 31], - [2000, 1, 1], - [2019, 2, 14], - [2020, 7, 4], - [2029, 12, 31], - [2525, 1, 1], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=DATE(2022,12,31)'); - $worksheet->setCellValue('G' . $row, '=DAYS360(D' . $row . ', F' . $row . ', FALSE)'); - $worksheet->setCellValue('H' . $row, '=DAYS360(D' . $row . ', F' . $row . ', TRUE)'); -} -$worksheet->getStyle('E1:F' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf( - 'Between: %s and %s', - $worksheet->getCell('E' . $row)->getFormattedValue(), - $worksheet->getCell('F' . $row)->getFormattedValue() - )); - $helper->log( - 'Days: ' - . $worksheet->getCell('G' . $row)->getCalculatedValueString() - . ' (US) ' - . $worksheet->getCell('H' . $row)->getCalculatedValueString() - . ' (European)' - ); -} diff --git a/samples/DateTime/EDATE.php b/samples/DateTime/EDATE.php deleted file mode 100644 index f224c391ce..0000000000 --- a/samples/DateTime/EDATE.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -$months = range(-12, 12); -$testDateCount = count($months); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('A' . $row, '=DATE(2020,12,31)'); - $worksheet->setCellValue('B' . $row, '=A' . $row); - $worksheet->setCellValue('C' . $row, $months[$row - 1]); - $worksheet->setCellValue('D' . $row, '=EDATE(B' . $row . ', C' . $row . ')'); -} -$worksheet->getStyle('B1:B' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->getStyle('D1:D' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - /** @var null|bool|float|int|string */ - $calc = $worksheet->getCell('D' . $row)->getCalculatedValue(); - $helper->log( - $worksheet->getCell('B' . $row)->getFormattedValue() - . ' and ' - . $worksheet->getCell('C' . $row)->getFormattedValue() - . ' months is ' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('D' . $row)->getFormattedValue() - . ')' - ); -} diff --git a/samples/DateTime/EOMONTH.php b/samples/DateTime/EOMONTH.php deleted file mode 100644 index e04f6859e5..0000000000 --- a/samples/DateTime/EOMONTH.php +++ /dev/null @@ -1,46 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -$months = range(-12, 12); -$testDateCount = count($months); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('A' . $row, '=DATE(2020,1,1)'); - $worksheet->setCellValue('B' . $row, '=A' . $row); - $worksheet->setCellValue('C' . $row, $months[$row - 1]); - $worksheet->setCellValue('D' . $row, '=EOMONTH(B' . $row . ', C' . $row . ')'); -} -$worksheet->getStyle('B1:B' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->getStyle('D1:D' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log( - $worksheet->getCell('B' . $row)->getFormattedValue() - . ' and ' - . $worksheet->getCell('C' . $row)->getFormattedValue() - . ' months is ' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ' (' - . $worksheet->getCell('D' . $row)->getFormattedValue() - . ')' - ); -} diff --git a/samples/DateTime/HOUR.php b/samples/DateTime/HOUR.php deleted file mode 100644 index 2282b62117..0000000000 --- a/samples/DateTime/HOUR.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testTimes = [ - [0, 6, 0], - [1, 12, 15], - [3, 30, 12], - [5, 17, 31], - [8, 15, 45], - [12, 45, 11], - [14, 0, 30], - [17, 55, 50], - [19, 21, 8], - [21, 10, 10], - [23, 59, 59], -]; -$testTimeCount = count($testTimes); - -$worksheet->fromArray($testTimes, null, 'A1', true); - -for ($row = 1; $row <= $testTimeCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=TIME(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=HOUR(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testTimeCount) - ->getNumberFormat() - ->setFormatCode('hh:mm:ss'); - -// Test the formulae -for ($row = 1; $row <= $testTimeCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Hour is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/ISOWEEKNUM.php b/samples/DateTime/ISOWEEKNUM.php deleted file mode 100644 index e27e70a517..0000000000 --- a/samples/DateTime/ISOWEEKNUM.php +++ /dev/null @@ -1,50 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=ISOWEEKNUM(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('ISO Week number is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/MINUTE.php b/samples/DateTime/MINUTE.php deleted file mode 100644 index 9b47d47e8a..0000000000 --- a/samples/DateTime/MINUTE.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testTimes = [ - [0, 6, 0], - [1, 12, 15], - [3, 30, 12], - [5, 17, 31], - [8, 15, 45], - [12, 45, 11], - [14, 0, 30], - [17, 55, 50], - [19, 21, 8], - [21, 10, 10], - [23, 59, 59], -]; -$testTimeCount = count($testTimes); - -$worksheet->fromArray($testTimes, null, 'A1', true); - -for ($row = 1; $row <= $testTimeCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=TIME(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=MINUTE(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testTimeCount) - ->getNumberFormat() - ->setFormatCode('hh:mm:ss'); - -// Test the formulae -for ($row = 1; $row <= $testTimeCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Minute is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime/MONTH.php b/samples/DateTime/MONTH.php deleted file mode 100644 index f3c814dc74..0000000000 --- a/samples/DateTime/MONTH.php +++ /dev/null @@ -1,50 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=MONTH(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Month is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime2/NETWORKDAYS.php b/samples/DateTime2/NETWORKDAYS.php deleted file mode 100644 index 063b0b2d3e..0000000000 --- a/samples/DateTime2/NETWORKDAYS.php +++ /dev/null @@ -1,70 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$publicHolidays = [ - [2022, 1, 3, '=DATE(G1, H1, I1)', 'New Year'], - [2022, 4, 15, '=DATE(G2, H2, I2)', 'Good Friday'], - [2022, 4, 18, '=DATE(G3, H3, I3)', 'Easter Monday'], - [2022, 5, 2, '=DATE(G4, H4, I4)', 'Early May Bank Holiday'], - [2022, 6, 2, '=DATE(G5, H5, I5)', 'Spring Bank Holiday'], - [2022, 6, 3, '=DATE(G6, H6, I6)', 'Platinum Jubilee Bank Holiday'], - [2022, 8, 29, '=DATE(G7, H7, I7)', 'Summer Bank Holiday'], - [2022, 12, 26, '=DATE(G8, H8, I8)', 'Boxing Day'], - [2022, 12, 27, '=DATE(G9, H9, I9)', 'Christmas Day'], -]; - -$holidayCount = count($publicHolidays); -$worksheet->fromArray($publicHolidays, null, 'G1', true); - -$worksheet->getStyle('J1:J' . $holidayCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->setCellValue('A1', '=DATE(2022,1,1)'); - -for ($numberOfMonths = 0; $numberOfMonths < 12; ++$numberOfMonths) { - $worksheet->setCellValue('B' . ($numberOfMonths + 1), '=EOMONTH(A1, ' . $numberOfMonths . ')'); - $worksheet->setCellValue('C' . ($numberOfMonths + 1), '=NETWORKDAYS(A1, B' . ($numberOfMonths + 1) . ')'); - $worksheet->setCellValue('D' . ($numberOfMonths + 1), '=NETWORKDAYS(A1, B' . ($numberOfMonths + 1) . ', J1:J' . $holidayCount . ')'); -} - -$worksheet->getStyle('A1') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->getStyle('B1:B12') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -$helper->log('UK Public Holidays'); -$holidayData = $worksheet->rangeToArray('J1:K' . $holidayCount, null, true, true, true); -$helper->displayGrid($holidayData); - -for ($row = 1; $row <= 12; ++$row) { - $helper->log( - 'Between ' - . $worksheet->getCell('A1')->getFormattedValue() - . ' and ' - . $worksheet->getCell('B' . $row)->getFormattedValue() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ' working days; ' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ' excluding public holidays' - ); -} diff --git a/samples/DateTime2/NOW.php b/samples/DateTime2/NOW.php deleted file mode 100644 index 1dcf50d3ad..0000000000 --- a/samples/DateTime2/NOW.php +++ /dev/null @@ -1,29 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -$worksheet->setCellValue('A1', '=NOW()'); -$worksheet->getStyle('A1') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd hh:mm:ss'); - -// Test the formulae -$helper->log( - 'Today is ' - . $worksheet->getCell('A1')->getCalculatedValueString() - . ' (' - . $worksheet->getCell('A1')->getFormattedValue() - . ')' -); diff --git a/samples/DateTime2/SECOND.php b/samples/DateTime2/SECOND.php deleted file mode 100644 index b49186f884..0000000000 --- a/samples/DateTime2/SECOND.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testTimes = [ - [0, 6, 0], - [1, 12, 15], - [3, 30, 12], - [5, 17, 31], - [8, 15, 45], - [12, 45, 11], - [14, 0, 30], - [17, 55, 50], - [19, 21, 8], - [21, 10, 10], - [23, 59, 59], -]; -$testTimeCount = count($testTimes); - -$worksheet->fromArray($testTimes, null, 'A1', true); - -for ($row = 1; $row <= $testTimeCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=TIME(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=SECOND(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testTimeCount) - ->getNumberFormat() - ->setFormatCode('hh:mm:ss'); - -// Test the formulae -for ($row = 1; $row <= $testTimeCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Second is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime2/TIME.php b/samples/DateTime2/TIME.php deleted file mode 100644 index 9cbfc4763f..0000000000 --- a/samples/DateTime2/TIME.php +++ /dev/null @@ -1,43 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [[3, 15], [13, 15], [15, 15, 15], [3, 15, 30], - [15, 15, 15], [5], [9, 15, 0], [9, 15, -1], - [13, -14, -15], [0, 0, -1], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=TIME(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('hh:mm:ss'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log("(A{$row}) Hour: " . $worksheet->getCell('A' . $row)->getFormattedValue()); - $helper->log("(B{$row}) Minute: " . $worksheet->getCell('B' . $row)->getFormattedValue()); - $helper->log("(C{$row}) Second: " . $worksheet->getCell('C' . $row)->getFormattedValue()); - $helper->log('Formula: ' . $worksheet->getCell('D' . $row)->getValueString()); - $helper->log('Excel TimeStamp: ' . $worksheet->getCell('D' . $row)->getCalculatedValueString()); - $helper->log('Formatted TimeStamp: ' . $worksheet->getCell('E' . $row)->getFormattedValue()); - $helper->log(''); -} diff --git a/samples/DateTime2/TIMEVALUE.php b/samples/DateTime2/TIMEVALUE.php deleted file mode 100644 index 819e39ef76..0000000000 --- a/samples/DateTime2/TIMEVALUE.php +++ /dev/null @@ -1,39 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = ['3:15', '13:15', '15:15:15', '3:15 AM', '3:15 PM', '5PM', '9:15AM', '13:15AM', -]; -$testDateCount = count($testDates); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('A' . $row, $testDates[$row - 1]); - $worksheet->setCellValue('B' . $row, '=TIMEVALUE(A' . $row . ')'); - $worksheet->setCellValue('C' . $row, '=B' . $row); -} - -$worksheet->getStyle('C1:C' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('hh:mm:ss'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log("(A{$row}) Time String: " . $worksheet->getCell('A' . $row)->getFormattedValue()); - $helper->log('Formula: ' . $worksheet->getCell('B' . $row)->getValueString()); - $helper->log('Excel TimeStamp: ' . $worksheet->getCell('B' . $row)->getFormattedValue()); - $helper->log('Formatted TimeStamp: ' . $worksheet->getCell('C' . $row)->getFormattedValue()); - $helper->log(''); -} diff --git a/samples/DateTime2/TODAY.php b/samples/DateTime2/TODAY.php deleted file mode 100644 index 8fa61d1ebf..0000000000 --- a/samples/DateTime2/TODAY.php +++ /dev/null @@ -1,29 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -$worksheet->setCellValue('A1', '=TODAY()'); -$worksheet->getStyle('A1') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -$helper->log( - 'Today is ' - . $worksheet->getCell('A1')->getCalculatedValueString() - . ' (' - . $worksheet->getCell('A1')->getFormattedValue() - . ')' -); diff --git a/samples/DateTime2/WEEKDAY.php b/samples/DateTime2/WEEKDAY.php deleted file mode 100644 index f28c89efdb..0000000000 --- a/samples/DateTime2/WEEKDAY.php +++ /dev/null @@ -1,60 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=WEEKDAY(D' . $row . ')'); - $worksheet->setCellValue('G' . $row, '=WEEKDAY(D' . $row . ', 2)'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log( - 'Weekday is: ' - . $worksheet->getCell('F' . $row)->getCalculatedValueString() - . ' (1-7 = Sun-Sat)' - ); - $helper->log( - 'Weekday is: ' - . $worksheet->getCell('G' . $row)->getCalculatedValueString() - . ' (1-7 = Mon-Sun)' - ); -} diff --git a/samples/DateTime2/WEEKNUM.php b/samples/DateTime2/WEEKNUM.php deleted file mode 100644 index 33cfed6dc8..0000000000 --- a/samples/DateTime2/WEEKNUM.php +++ /dev/null @@ -1,52 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=WEEKNUM(D' . $row . ')'); - $worksheet->setCellValue('G' . $row, '=WEEKNUM(D' . $row . ', 21)'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('System 1 Week number is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); - $helper->log('System 2 (ISO-8601) Week number is: ' . $worksheet->getCell('G' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime2/WORKDAY.php b/samples/DateTime2/WORKDAY.php deleted file mode 100644 index 6358087256..0000000000 --- a/samples/DateTime2/WORKDAY.php +++ /dev/null @@ -1,67 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$publicHolidays = [ - [2022, 1, 3, '=DATE(G1, H1, I1)', 'New Year'], - [2022, 4, 15, '=DATE(G2, H2, I2)', 'Good Friday'], - [2022, 4, 18, '=DATE(G3, H3, I3)', 'Easter Monday'], - [2022, 5, 2, '=DATE(G4, H4, I4)', 'Early May Bank Holiday'], - [2022, 6, 2, '=DATE(G5, H5, I5)', 'Spring Bank Holiday'], - [2022, 6, 3, '=DATE(G6, H6, I6)', 'Platinum Jubilee Bank Holiday'], - [2022, 8, 29, '=DATE(G7, H7, I7)', 'Summer Bank Holiday'], - [2022, 12, 26, '=DATE(G8, H8, I8)', 'Boxing Day'], - [2022, 12, 27, '=DATE(G9, H9, I9)', 'Christmas Day'], -]; - -$holidayCount = count($publicHolidays); -$worksheet->fromArray($publicHolidays, null, 'G1', true); - -$worksheet->getStyle('J1:J' . $holidayCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->setCellValue('A1', '=DATE(2022,1,1)'); - -$workdayStep = 10; -for ($days = $workdayStep; $days <= 366; $days += $workdayStep) { - $worksheet->setCellValue('B' . ((int) $days / $workdayStep + 1), $days); - $worksheet->setCellValue('C' . ((int) $days / $workdayStep + 1), '=WORKDAY(A1, B' . ((int) $days / $workdayStep + 1) . ')'); - $worksheet->setCellValue('D' . ((int) $days / $workdayStep + 1), '=WORKDAY(A1, B' . ((int) $days / $workdayStep + 1) . ', J1:J' . $holidayCount . ')'); -} - -$worksheet->getStyle('A1') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -$worksheet->getStyle('C1:D50') - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -$helper->log('UK Public Holidays'); -$holidayData = $worksheet->rangeToArray('J1:K' . $holidayCount, null, true, true, true); -$helper->displayGrid($holidayData); - -for ($days = $workdayStep; $days <= 366; $days += $workdayStep) { - $helper->log(sprintf( - '%d workdays from %s is %s; %s with public holidays', - $worksheet->getCell('B' . ((int) $days / $workdayStep + 1))->getFormattedValue(), - $worksheet->getCell('A1')->getFormattedValue(), - $worksheet->getCell('C' . ((int) $days / $workdayStep + 1))->getFormattedValue(), - $worksheet->getCell('D' . ((int) $days / $workdayStep + 1))->getFormattedValue() - )); -} diff --git a/samples/DateTime2/YEAR.php b/samples/DateTime2/YEAR.php deleted file mode 100644 index 0924595a6f..0000000000 --- a/samples/DateTime2/YEAR.php +++ /dev/null @@ -1,50 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 2, 14], - [1936, 3, 17], - [1964, 4, 29], - [1999, 5, 18], - [2000, 6, 21], - [2019, 7, 4], - [2020, 8, 31], - [1956, 9, 10], - [2010, 10, 10], - [1982, 11, 30], - [1960, 12, 19], - ['=YEAR(TODAY())', '=MONTH(TODAY())', '=DAY(TODAY())'], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=YEAR(D' . $row . ')'); -} -$worksheet->getStyle('E1:E' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf('(E%d): %s', $row, $worksheet->getCell('E' . $row)->getFormattedValue())); - $helper->log('Year is: ' . $worksheet->getCell('F' . $row)->getCalculatedValueString()); -} diff --git a/samples/DateTime2/YEARFRAC.php b/samples/DateTime2/YEARFRAC.php deleted file mode 100644 index 465624cc06..0000000000 --- a/samples/DateTime2/YEARFRAC.php +++ /dev/null @@ -1,81 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testDates = [ - [1900, 1, 1], - [1904, 1, 1], - [1936, 3, 17], - [1960, 12, 19], - [1999, 12, 31], - [2000, 1, 1], - [2019, 2, 14], - [2020, 7, 4], - [2020, 2, 29], - [2029, 12, 31], - [2525, 1, 1], -]; -$testDateCount = count($testDates); - -$worksheet->fromArray($testDates, null, 'A1', true); - -for ($row = 1; $row <= $testDateCount; ++$row) { - $worksheet->setCellValue('D' . $row, '=DATE(A' . $row . ',B' . $row . ',C' . $row . ')'); - $worksheet->setCellValue('E' . $row, '=D' . $row); - $worksheet->setCellValue('F' . $row, '=DATE(2022,12,31)'); - $worksheet->setCellValue('G' . $row, '=YEARFRAC(D' . $row . ', F' . $row . ')'); - $worksheet->setCellValue('H' . $row, '=YEARFRAC(D' . $row . ', F' . $row . ', 1)'); - $worksheet->setCellValue('I' . $row, '=YEARFRAC(D' . $row . ', F' . $row . ', 2)'); - $worksheet->setCellValue('J' . $row, '=YEARFRAC(D' . $row . ', F' . $row . ', 3)'); - $worksheet->setCellValue('K' . $row, '=YEARFRAC(D' . $row . ', F' . $row . ', 4)'); -} -$worksheet->getStyle('E1:F' . $testDateCount) - ->getNumberFormat() - ->setFormatCode('yyyy-mm-dd'); - -// Test the formulae -for ($row = 1; $row <= $testDateCount; ++$row) { - $helper->log(sprintf( - 'Between: %s and %s', - $worksheet->getCell('E' . $row)->getFormattedValue(), - $worksheet->getCell('F' . $row)->getFormattedValue() - )); - $helper->log( - 'Days: ' - . $worksheet->getCell('G' . $row)->getCalculatedValueString() - . ' - US (NASD) 30/360' - ); - $helper->log( - 'Days: ' - . $worksheet->getCell('H' . $row)->getCalculatedValueString() - . ' - Actual' - ); - $helper->log( - 'Days: ' - . $worksheet->getCell('I' . $row)->getCalculatedValueString() - . ' - Actual/360' - ); - $helper->log( - 'Days: ' - . $worksheet->getCell('J' . $row)->getCalculatedValueString() - . ' - Actual/365' - ); - $helper->log( - 'Days: ' - . $worksheet->getCell('K' . $row)->getCalculatedValueString() - . ' - European 30/360' - ); -} diff --git a/samples/DefinedNames/AbsoluteNamedRange.php b/samples/DefinedNames/AbsoluteNamedRange.php deleted file mode 100644 index d9451bafa6..0000000000 --- a/samples/DefinedNames/AbsoluteNamedRange.php +++ /dev/null @@ -1,60 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named range using an absolute cell reference -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", "=B{$row}*CHARGE_RATE"); - ++$row; -} -$endRow = $row - 1; - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(B{$startRow}:B{$endRow})") - ->setCellValue("C{$row}", "=SUM(C{$startRow}:C{$endRow})"); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B1')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $value, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/CrossWorksheetNamedFormula.php b/samples/DefinedNames/CrossWorksheetNamedFormula.php deleted file mode 100644 index 5c6b20259c..0000000000 --- a/samples/DefinedNames/CrossWorksheetNamedFormula.php +++ /dev/null @@ -1,91 +0,0 @@ -setActiveSheetIndex(0); -setYearlyData($worksheet, '2019', $data2019); -$worksheet = $spreadsheet->addSheet(new Worksheet($spreadsheet)); -setYearlyData($worksheet, '2020', $data2020); -$worksheet = $spreadsheet->addSheet(new Worksheet($spreadsheet)); -setYearlyData($worksheet, '2020', [], 'GROWTH'); - -/** @param array> $yearlyData */ -function setYearlyData(Worksheet $worksheet, string $year, array $yearlyData, ?string $title = null): void -{ - // Set up some basic data - $worksheetTitle = $title ?: $year; - $worksheet - ->setTitle($worksheetTitle) - ->setCellValue('A1', 'Month') - ->setCellValue('B1', $worksheetTitle === 'GROWTH' ? 'Growth' : 'Sales') - ->setCellValue('C1', $worksheetTitle === 'GROWTH' ? 'Profit Growth' : 'Margin') - ->setCellValue('A2', Date::stringToExcel("{$year}-01-01")); - for ($row = 3; $row <= 13; ++$row) { - $worksheet->setCellValue("A{$row}", '=NEXT_MONTH'); - } - - if (!empty($yearlyData)) { - $worksheet->fromArray($yearlyData, null, 'B2'); - } else { - for ($row = 2; $row <= 13; ++$row) { - $worksheet->setCellValue("B{$row}", '=GROWTH'); - $worksheet->setCellValue("C{$row}", '=PROFIT_GROWTH'); - } - } - - $worksheet->getStyle('A1:C1') - ->getFont()->setBold(true); - $worksheet->getStyle('A2:A13') - ->getNumberFormat() - ->setFormatCode('mmmm'); - $worksheet->getStyle('B2:C13') - ->getNumberFormat() - ->setFormatCode($worksheetTitle === 'GROWTH' ? '0.00%' : '_-€* #,##0_-'); -} - -// Add some Named Formulae -// The first to store our tax rate -$spreadsheet->addNamedFormula(new NamedFormula('NEXT_MONTH', $worksheet, '=EDATE(OFFSET($A1,-1,0),1)')); -$spreadsheet->addNamedFormula(new NamedFormula('GROWTH', $worksheet, "=IF('2020'!\$B1=\"\",\"-\",(('2020'!\$B1/'2019'!\$B1)-1))")); -$spreadsheet->addNamedFormula(new NamedFormula('PROFIT_GROWTH', $worksheet, "=IF('2020'!\$C1=\"\",\"-\",(('2020'!\$C1/'2019'!\$C1)-1))")); - -for ($row = 2; $row <= 7; ++$row) { - $month = $worksheet->getCell("A{$row}")->getFormattedValue(); - $growth = $worksheet->getCell("B{$row}")->getFormattedValue(); - $profitGrowth = $worksheet->getCell("C{$row}")->getFormattedValue(); - - $helper->log("Growth for {$month} is {$growth}, with a Profit Growth of {$profitGrowth}"); -} - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/NamedFormulaeAndRanges.php b/samples/DefinedNames/NamedFormulaeAndRanges.php deleted file mode 100644 index 36986ceb91..0000000000 --- a/samples/DefinedNames/NamedFormulaeAndRanges.php +++ /dev/null @@ -1,71 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); -// Set up the formula for calculating the daily charge -$spreadsheet->addNamedFormula(new NamedFormula('DAILY_CHARGE', null, '=HOURS_PER_DAY*CHARGE_RATE')); -// Set up the formula for calculating the column totals -$spreadsheet->addNamedFormula(new NamedFormula('COLUMN_TOTALS', null, '=SUM(COLUMN_DATA_VALUES)')); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=DAILY_CHARGE'); - ++$row; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange(new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}")); - -++$row; -$worksheet - ->setCellValue("B{$row}", '=COLUMN_TOTALS') - ->setCellValue("C{$row}", '=COLUMN_TOTALS'); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B1')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $value, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/RelativeNamedRange.php b/samples/DefinedNames/RelativeNamedRange.php deleted file mode 100644 index 11c8534ced..0000000000 --- a/samples/DefinedNames/RelativeNamedRange.php +++ /dev/null @@ -1,63 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=HOURS_PER_DAY*CHARGE_RATE'); - ++$row; -} -$endRow = $row - 1; - -++$row; -$worksheet - ->setCellValue("B{$row}", "=SUM(B{$startRow}:B{$endRow})") - ->setCellValue("C{$row}", "=SUM(C{$startRow}:C{$endRow})"); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B1')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $value, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/RelativeNamedRange2.php b/samples/DefinedNames/RelativeNamedRange2.php deleted file mode 100644 index b8bf237c0a..0000000000 --- a/samples/DefinedNames/RelativeNamedRange2.php +++ /dev/null @@ -1,66 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=HOURS_PER_DAY*CHARGE_RATE'); - ++$row; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange(new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}")); - -++$row; -$worksheet - ->setCellValue("B{$row}", '=SUM(COLUMN_DATA_VALUES)') - ->setCellValue("C{$row}", '=SUM(COLUMN_DATA_VALUES)'); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B1')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $value, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/RelativeNamedRangeAsFunction.php b/samples/DefinedNames/RelativeNamedRangeAsFunction.php deleted file mode 100644 index e4b5f11f41..0000000000 --- a/samples/DefinedNames/RelativeNamedRangeAsFunction.php +++ /dev/null @@ -1,69 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - -// Define named ranges -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 4; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=HOURS_PER_DAY*CHARGE_RATE'); - ++$row; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -// To avoid including the current row,or having to hard-code the range itself (as we did in the previous example) -// we wrap it in a named formula using the OFFSET() function -$spreadsheet->addNamedFormula(new NamedFormula('COLUMN_DATA_VALUES', $worksheet, '=OFFSET(A$4:A1, -1, 0)')); - -++$row; -$worksheet - ->setCellValue("B{$row}", '=SUM(COLUMN_DATA_VALUES)') - ->setCellValue("C{$row}", '=SUM(COLUMN_DATA_VALUES)'); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B1')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $value, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/ScopedNamedRange.php b/samples/DefinedNames/ScopedNamedRange.php deleted file mode 100644 index ea5df665ae..0000000000 --- a/samples/DefinedNames/ScopedNamedRange.php +++ /dev/null @@ -1,85 +0,0 @@ -setActiveSheetIndex(0); -$worksheet->setTitle('Base Data'); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50'); - -// Define a global named range on the first worksheet for our Charge Rate -// CHARGE_RATE is an absolute cell reference that always points to cell B1 -// Because it is defined globally, it will still be usable from any worksheet in the spreadsheet -$spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1')); - -// Create a second worksheet as our client timesheet -$worksheet = $spreadsheet->addSheet(new PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, 'Client Timesheet')); - -// Define named ranges -// HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used -$spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1')); - -// Set up some basic data for a timesheet -$worksheet - ->setCellValue('A1', 'Date') - ->setCellValue('B1', 'Hours') - ->setCellValue('C1', 'Charge'); - -$workHours = [ - '2020-0-06' => 7.5, - '2020-0-07' => 7.25, - '2020-0-08' => 6.5, - '2020-0-09' => 7.0, - '2020-0-10' => 5.5, -]; - -// Populate the Timesheet -$startRow = 2; -$row = $startRow; -foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=HOURS_PER_DAY*CHARGE_RATE'); - ++$row; -} -$endRow = $row - 1; - -// COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used -$spreadsheet->addNamedRange(new NamedRange('COLUMN_DATA_VALUES', $worksheet, "=A\${$startRow}:A\${$endRow}")); - -++$row; -$worksheet - ->setCellValue("B{$row}", '=SUM(COLUMN_DATA_VALUES)') - ->setCellValue("C{$row}", '=SUM(COLUMN_DATA_VALUES)'); - -$range = $spreadsheet->getNamedRange('CHARGE_RATE'); -if ($range === null || $range->getWorksheet() === null) { - throw new Exception('expected named range not found'); -} -/** @var string */ -$cellsInRange0 = $range->getCellsInRange()[0]; -/** @var float */ -$chargeRateCellValue = $spreadsheet - ->getSheetByNameOrThrow($range->getWorksheet()->getTitle()) - ->getCell($cellsInRange0)->getValue(); - -/** @var float */ -$calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); -/** @var float */ -$calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); -$helper->log(sprintf( - 'Worked %.2f hours at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $chargeRateCellValue, - $calc2 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/ScopedNamedRange2.php b/samples/DefinedNames/ScopedNamedRange2.php deleted file mode 100644 index da5331087f..0000000000 --- a/samples/DefinedNames/ScopedNamedRange2.php +++ /dev/null @@ -1,95 +0,0 @@ -setActiveSheetIndex(0); - -$clients = [ - 'Client #1 - Full Hourly Rate' => [ - '2020-0-06' => 2.5, - '2020-0-07' => 2.25, - '2020-0-08' => 6.0, - '2020-0-09' => 3.0, - '2020-0-10' => 2.25, - ], - 'Client #2 - Full Hourly Rate' => [ - '2020-0-06' => 1.5, - '2020-0-07' => 2.75, - '2020-0-08' => 0.0, - '2020-0-09' => 4.5, - '2020-0-10' => 3.5, - ], - 'Client #3 - Reduced Hourly Rate' => [ - '2020-0-06' => 3.5, - '2020-0-07' => 2.5, - '2020-0-08' => 1.5, - '2020-0-09' => 0.0, - '2020-0-10' => 1.25, - ], -]; - -foreach ($clients as $clientName => $workHours) { - $worksheet = $spreadsheet->addSheet(new PhpOffice\PhpSpreadsheet\Worksheet\Worksheet($spreadsheet, $clientName)); - - // Set up some basic data for a timesheet - $worksheet - ->setCellValue('A1', 'Charge Rate/hour:') - ->setCellValue('B1', '7.50') - ->setCellValue('A3', 'Date') - ->setCellValue('B3', 'Hours') - ->setCellValue('C3', 'Charge'); - - // Define named ranges - // CHARGE_RATE is an absolute cell reference that always points to cell B1 - $spreadsheet->addNamedRange(new NamedRange('CHARGE_RATE', $worksheet, '=$B$1', true)); - // HOURS_PER_DAY is a relative cell reference that always points to column B, but to a cell in the row where it is used - $spreadsheet->addNamedRange(new NamedRange('HOURS_PER_DAY', $worksheet, '=$B1', true)); - - // Populate the Timesheet - $startRow = 4; - $row = $startRow; - foreach ($workHours as $date => $hours) { - $worksheet - ->setCellValue("A{$row}", $date) - ->setCellValue("B{$row}", $hours) - ->setCellValue("C{$row}", '=HOURS_PER_DAY*CHARGE_RATE'); - ++$row; - } - $endRow = $row - 1; - - // COLUMN_TOTAL is another relative cell reference that always points to the same range of rows but to cell in the column where it is used - $spreadsheet->addNamedRange(new NamedRange('COLUMN_TOTAL', $worksheet, "=A\${$startRow}:A\${$endRow}", true)); - - ++$row; - $worksheet - ->setCellValue("B{$row}", '=SUM(COLUMN_TOTAL)') - ->setCellValue("C{$row}", '=SUM(COLUMN_TOTAL)'); -} -$spreadsheet->removeSheetByIndex(0); - -// Set the reduced charge rate for our special client -$worksheet - ->setCellValue('B1', 4.5); - -foreach ($spreadsheet->getAllSheets() as $worksheet) { - /** @var float */ - $calc1 = $worksheet->getCell("B{$row}")->getCalculatedValue(); - /** @var float */ - $value = $worksheet->getCell('B1')->getValue(); - /** @var float */ - $calc2 = $worksheet->getCell("C{$row}")->getCalculatedValue(); - $helper->log(sprintf( - 'Worked %.2f hours for "%s" at a rate of %.2f - Charge to the client is %.2f', - $calc1, - $worksheet->getTitle(), - $value, - $calc2 - )); -} -$worksheet = $spreadsheet->setActiveSheetIndex(0); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/SimpleNamedFormula.php b/samples/DefinedNames/SimpleNamedFormula.php deleted file mode 100644 index a407176908..0000000000 --- a/samples/DefinedNames/SimpleNamedFormula.php +++ /dev/null @@ -1,51 +0,0 @@ -setActiveSheetIndex(0); - -// Add some Named Formulae -// The first to store our tax rate -$spreadsheet->addNamedFormula(new NamedFormula('TAX_RATE', $worksheet, '=19%')); -// The second to calculate the Tax on a Price value (Note that `PRICE` is defined later as a Named Range) -$spreadsheet->addNamedFormula(new NamedFormula('TAX', $worksheet, '=PRICE*TAX_RATE')); - -// Set up some basic data -$worksheet - ->setCellValue('A1', 'Tax Rate:') - ->setCellValue('B1', '=TAX_RATE') - ->setCellValue('A3', 'Net Price:') - ->setCellValue('B3', 19.99) - ->setCellValue('A4', 'Tax:') - ->setCellValue('A5', 'Price including Tax:'); - -// Define a named range that we can use in our formulae -$spreadsheet->addNamedRange(new NamedRange('PRICE', $worksheet, '=$B$3')); - -// Reference the defined formulae in worksheet formulae -$worksheet - ->setCellValue('B4', '=TAX') - ->setCellValue('B5', '=PRICE+TAX'); - -/** @var float */ -$calc1 = $worksheet->getCell('B1')->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B3')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell('B4')->getCalculatedValue(); -/** @var float */ -$calc3 = $worksheet->getCell('B5')->getCalculatedValue(); -$helper->log(sprintf( - 'With a Tax Rate of %.2f and a net price of %.2f, Tax is %.2f and the gross price is %.2f', - $calc1, - $value, - $calc2, - $calc3 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/DefinedNames/SimpleNamedRange.php b/samples/DefinedNames/SimpleNamedRange.php deleted file mode 100644 index b80b213bef..0000000000 --- a/samples/DefinedNames/SimpleNamedRange.php +++ /dev/null @@ -1,45 +0,0 @@ -setActiveSheetIndex(0); - -// Set up some basic data -$worksheet - ->setCellValue('A1', 'Tax Rate:') - ->setCellValue('B1', '=19%') - ->setCellValue('A3', 'Net Price:') - ->setCellValue('B3', 12.99) - ->setCellValue('A4', 'Tax:') - ->setCellValue('A5', 'Price including Tax:'); - -// Define named ranges -$spreadsheet->addNamedRange(new NamedRange('TAX_RATE', $worksheet, '=$B$1')); -$spreadsheet->addNamedRange(new NamedRange('PRICE', $worksheet, '=$B$3')); - -// Reference that defined name in a formula -$worksheet - ->setCellValue('B4', '=PRICE*TAX_RATE') - ->setCellValue('B5', '=PRICE*(1+TAX_RATE)'); - -/** @var float */ -$calc1 = $worksheet->getCell('B1')->getCalculatedValue(); -/** @var float */ -$value = $worksheet->getCell('B3')->getValue(); -/** @var float */ -$calc2 = $worksheet->getCell('B4')->getCalculatedValue(); -/** @var float */ -$calc3 = $worksheet->getCell('B5')->getCalculatedValue(); -$helper->log(sprintf( - 'With a Tax Rate of %.2f and a net price of %.2f, Tax is %.2f and the gross price is %.2f', - $calc1, - $value, - $calc2, - $calc3 -)); - -$helper->write($spreadsheet, __FILE__, ['Xlsx']); diff --git a/samples/Engineering/BESSELI.php b/samples/Engineering/BESSELI.php deleted file mode 100644 index eeed87e0a0..0000000000 --- a/samples/Engineering/BESSELI.php +++ /dev/null @@ -1,26 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -for ($n = 0; $n <= 5; ++$n) { - for ($x = 0; $x <= 5; $x = $x + 0.25) { - Calculation::getInstance($spreadsheet)->flushInstance(); - $formula = "BESSELI({$x}, {$n})"; - $worksheet->setCellValue('A1', "=$formula"); - - $helper->log("$formula = " . $worksheet->getCell('A1')->getCalculatedValueString()); - } -} diff --git a/samples/Engineering/BESSELJ.php b/samples/Engineering/BESSELJ.php deleted file mode 100644 index 647737f72a..0000000000 --- a/samples/Engineering/BESSELJ.php +++ /dev/null @@ -1,26 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -for ($n = 0; $n <= 5; ++$n) { - for ($x = 0; $x <= 5; $x = $x + 0.25) { - Calculation::getInstance($spreadsheet)->flushInstance(); - $formula = "BESSELJ({$x}, {$n})"; - $worksheet->setCellValue('A1', "=$formula"); - - $helper->log("$formula = " . $worksheet->getCell('A1')->getCalculatedValueString()); - } -} diff --git a/samples/Engineering/BESSELK.php b/samples/Engineering/BESSELK.php deleted file mode 100644 index ae16587c48..0000000000 --- a/samples/Engineering/BESSELK.php +++ /dev/null @@ -1,26 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -for ($n = 0; $n <= 5; ++$n) { - for ($x = 0; $x <= 5; $x = $x + 0.25) { - Calculation::getInstance($spreadsheet)->flushInstance(); - $formula = "BESSELK({$x}, {$n})"; - $worksheet->setCellValue('A1', "=$formula"); - - $helper->log("$formula = " . $worksheet->getCell('A1')->getCalculatedValueString()); - } -} diff --git a/samples/Engineering/BESSELY.php b/samples/Engineering/BESSELY.php deleted file mode 100644 index 5671b1161a..0000000000 --- a/samples/Engineering/BESSELY.php +++ /dev/null @@ -1,26 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -for ($n = 0; $n <= 5; ++$n) { - for ($x = 0; $x <= 5; $x = $x + 0.25) { - Calculation::getInstance($spreadsheet)->flushInstance(); - $formula = "BESSELY({$x}, {$n})"; - $worksheet->setCellValue('A1', "=$formula"); - - $helper->log("$formula = " . $worksheet->getCell('A1')->getCalculatedValueString()); - } -} diff --git a/samples/Engineering/CONVERT.php b/samples/Engineering/CONVERT.php deleted file mode 100644 index a2f8d74f07..0000000000 --- a/samples/Engineering/CONVERT.php +++ /dev/null @@ -1,62 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$conversions = [ - [1, 'lbm', 'kg'], - [1, 'gal', 'l'], - [24, 'in', 'ft'], - [100, 'yd', 'm'], - [500, 'mi', 'km'], - [7.5, 'min', 'sec'], - [5, 'F', 'C'], - [32, 'C', 'K'], - [100, 'm2', 'ft2'], -]; -$testDataCount = count($conversions); - -$worksheet->fromArray($conversions, null, 'A1'); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $data = $conversions[$row - 1]; - $worksheet->setCellValue("D$row", "=CONVERT({$data[0]},\"{$data[1]}\",\"{$data[2]}\")"); -} - -$worksheet->setCellValue('H1', '=CONVERT(CONVERT(100,"m","ft"),"m","ft")'); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(A$row): Unit of Measure Conversion Formula " - . $worksheet->getCell('D' . $row)->getValueString() - . ' - ' - . $worksheet->getCell('A' . $row)->getValueString() - . ' ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('D' . $row)->getCalculatedValueString() - . ' ' - . $worksheet->getCell('C' . $row)->getValueString() - ); -} - -$helper->log('Old method for area conversions, before MS Excel introduced area Units of Measure'); - -$helper->log( - "(A$row): Unit of Measure Conversion Formula " - . $worksheet->getCell('H1')->getValueString() - . ' result is ' - . $worksheet->getCell('H1')->getCalculatedValueString() -); diff --git a/samples/Engineering/Convert-Online.php b/samples/Engineering/Convert-Online.php deleted file mode 100644 index 3f8da04bd1..0000000000 --- a/samples/Engineering/Convert-Online.php +++ /dev/null @@ -1,99 +0,0 @@ -isCli()) { - $helper->log('This example should only be run from a Web Browser' . PHP_EOL); - - return; -} -$post = []; -foreach (['category', 'quantity', 'fromUnit', 'toUnit'] as $value) { - if (isset($_POST[$value])) { - $post[$value] = StringHelper::convertToString($_POST[$value]); - } -} -$categories = ConvertUOM::getConversionCategories(); -$defaultCategory = $post['category'] ?? $categories[0]; -$units = []; -foreach ($categories as $category) { - $categoryUnits = ConvertUOM::getConversionCategoryUnitDetails($category)[$category]; - $categoryUnits = array_unique( - array_combine( - array_column($categoryUnits, 'unit'), - array_column($categoryUnits, 'description') - ) - ); - $units[$category] = $categoryUnits; -} - -?> -
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
-
-
-
- -log('Quantity is not numeric'); - } elseif (isset($units[$post['category']][$fromUnit], $units[$post['category']][$toUnit])) { - /** @var float|string */ - $result = ConvertUOM::CONVERT($quantity, $fromUnit, $toUnit); - - $helper->log("{$quantity} {$units[$post['category']][$fromUnit]} is {$result} {$units[$post['category']][$toUnit]}"); - } else { - $helper->log('Please enter quantity and select From Unit and To Unit'); - } -} else { - $helper->log('Please enter quantity and select From Unit and To Unit'); -} diff --git a/samples/Engineering/DELTA.php b/samples/Engineering/DELTA.php deleted file mode 100644 index 3ec8831145..0000000000 --- a/samples/Engineering/DELTA.php +++ /dev/null @@ -1,48 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [4, 5], - [3, 3], - [0.5, 0], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=DELTA(A' . $row . ',B' . $row . ')'); -} - -$comparison = [ - 0 => 'The values are not equal', - 1 => 'The values are equal', -]; - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): Compare values " - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' - Result is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - . ' - ' - . $comparison[$worksheet->getCell('C' . $row)->getCalculatedValueString()] - ); -} diff --git a/samples/Engineering/ERF.php b/samples/Engineering/ERF.php deleted file mode 100644 index bd6d0b4b6a..0000000000 --- a/samples/Engineering/ERF.php +++ /dev/null @@ -1,70 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData1 = [ - [0.745], - [1], - [1.5], - [-2], -]; - -$testData2 = [ - [0, 1.5], - [1, 2], - [-2, 1], -]; -$testDataCount1 = count($testData1); -$testDataCount2 = count($testData2); -$testData2StartRow = $testDataCount1 + 1; - -$worksheet->fromArray($testData1, null, 'A1', true); -$worksheet->fromArray($testData2, null, "A{$testData2StartRow}", true); - -for ($row = 1; $row <= $testDataCount1; ++$row) { - $worksheet->setCellValue('C' . $row, '=ERF(A' . $row . ')'); -} - -for ($row = $testDataCount1 + 1; $row <= $testDataCount2 + $testDataCount1; ++$row) { - $worksheet->setCellValue('C' . $row, '=ERF(A' . $row . ', B' . $row . ')'); -} - -// Test the formulae -$helper->log('ERF() With a single argument'); -for ($row = 1; $row <= $testDataCount1; ++$row) { - $helper->log( - "(C$row): " - . $worksheet->getCell('C' . $row)->getValueString() - . ' The error function integrated between 0 and ' - . $worksheet->getCell('A' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} - -$helper->log('ERF() With two arguments'); -for ($row = $testDataCount1 + 1; $row <= $testDataCount2 + $testDataCount1; ++$row) { - $helper->log( - "(C$row): " - . $worksheet->getCell('C' . $row)->getValueString() - . ' The error function integrated between ' - . $worksheet->getCell('A' . $row)->getValueString() - . ' and ' - . $worksheet->getCell('B' . $row)->getValueString() - . ' is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/Engineering/ERFC.php b/samples/Engineering/ERFC.php deleted file mode 100644 index addd02bb2a..0000000000 --- a/samples/Engineering/ERFC.php +++ /dev/null @@ -1,42 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [0], - [0.5], - [1], - [-1], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=ERFC(A' . $row . ')'); -} - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - $helper->log( - "(E$row): " - . $worksheet->getCell('C' . $row)->getValueString() - . ' The complementary error function integrated by ' - . $worksheet->getCell('A' . $row)->getValueString() - . ' and infinity is ' - . $worksheet->getCell('C' . $row)->getCalculatedValueString() - ); -} diff --git a/samples/Engineering/GESTEP.php b/samples/Engineering/GESTEP.php deleted file mode 100644 index e52574d596..0000000000 --- a/samples/Engineering/GESTEP.php +++ /dev/null @@ -1,59 +0,0 @@ -titles($category, $functionName, $description); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$testData = [ - [5, 4], - [5, 5], - [4, 5], - [-4, -5], - [-5, -4], - [1], -]; -$testDataCount = count($testData); - -$worksheet->fromArray($testData, null, 'A1', true); - -for ($row = 1; $row <= $testDataCount; ++$row) { - $worksheet->setCellValue('C' . $row, '=GESTEP(A' . $row . ',B' . $row . ')'); -} - -$comparison = [ - 0 => 'Value %d is less than step %d', - 1 => 'Value %d is greater than or equal to step %d', -]; - -// Test the formulae -for ($row = 1; $row <= $testDataCount; ++$row) { - /** @var int */ - $aValue = $worksheet->getCell('A' . $row)->getValue(); - /** @var int */ - $bValue = $worksheet->getCell('B' . $row)->getValue(); - /** @var int */ - $cValue = $worksheet->getCell('C' . $row)->getCalculatedValue(); - $helper->log(sprintf( - '(E%d): Compare value %d and step %d - Result is %d - %s', - $row, - $aValue, - $bValue, - $cValue, - sprintf( - $comparison[$cValue], - $aValue, - $bValue, - ) - )); -} diff --git a/samples/Financial1/ACCRINT.php b/samples/Financial1/ACCRINT.php deleted file mode 100644 index a57e95c8eb..0000000000 --- a/samples/Financial1/ACCRINT.php +++ /dev/null @@ -1,35 +0,0 @@ -log('Returns the accrued interest for a security that pays periodic interest.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Issue Date', DateHelper::getDateValue('01-Jan-2012')], - ['First Interest Date', DateHelper::getDateValue('01-Apr-2012')], - ['Settlement Date', DateHelper::getDateValue('31-Dec-2013')], - ['Annual Coupon Rate', 0.08], - ['Par Value', 10000], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B5')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B10', '=ACCRINT(B1, B2, B3, B4, B5, B6)'); -$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B10')->getValue()); -$helper->log('ACCRINT() Result is ' . $worksheet->getCell('B10')->getFormattedValue()); diff --git a/samples/Financial1/ACCRINTM.php b/samples/Financial1/ACCRINTM.php deleted file mode 100644 index 62ccaf05e6..0000000000 --- a/samples/Financial1/ACCRINTM.php +++ /dev/null @@ -1,33 +0,0 @@ -log('Returns the accrued interest for a security that pays interest at maturity.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Issue Date', DateHelper::getDateValue('01-Jan-2012')], - ['Settlement Date', DateHelper::getDateValue('31-Dec-2012')], - ['Annual Coupon Rate', 0.08], - ['Par Value', 10000], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B6', '=ACCRINTM(B1, B2, B3, B4)'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('ACCRINTM() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/AMORDEGRC.php b/samples/Financial1/AMORDEGRC.php deleted file mode 100644 index 3c1d057493..0000000000 --- a/samples/Financial1/AMORDEGRC.php +++ /dev/null @@ -1,38 +0,0 @@ -log('Returns the prorated linear depreciation of an asset for a specified accounting period.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Cost', 150.00], - ['Date Purchased', DateHelper::getDateValue('01-Jan-2015')], - ['First Period Date', DateHelper::getDateValue('30-Sep-2015')], - ['Salvage Value', 20.00], - ['Number of Periods', 1], - ['Depreciation Rate', 0.20], - ['Basis', FinancialConstants::BASIS_DAYS_PER_YEAR_360_EUROPEAN], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00'); -$worksheet->getStyle('B2:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -$worksheet->setCellValue('B10', '=AMORDEGRC(B1, B2, B3, B4, B5, B6, B7)'); -$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B10')->getValue()); -$helper->log('AMORDEGRC() Result is ' . $worksheet->getCell('B10')->getFormattedValue()); diff --git a/samples/Financial1/AMORLINC.php b/samples/Financial1/AMORLINC.php deleted file mode 100644 index 61f29e7aaf..0000000000 --- a/samples/Financial1/AMORLINC.php +++ /dev/null @@ -1,38 +0,0 @@ -log('Returns the prorated linear depreciation of an asset for a specified accounting period.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Cost', 150.00], - ['Date Purchased', DateHelper::getDateValue('01-Jan-2015')], - ['First Period Date', DateHelper::getDateValue('30-Sep-2015')], - ['Salvage Value', 20.00], - ['Period', 1], - ['Depreciation Rate', 0.20], - ['Basis', FinancialConstants::BASIS_DAYS_PER_YEAR_360_EUROPEAN], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00'); -$worksheet->getStyle('B2:B3')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B4')->getNumberFormat()->setFormatCode('$#,##0.00'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -$worksheet->setCellValue('B10', '=AMORLINC(B1, B2, B3, B4, B5, B6, B7)'); -$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B10')->getValue()); -$helper->log('AMORLINC() Result is ' . $worksheet->getCell('B10')->getFormattedValue()); diff --git a/samples/Financial1/COUPDAYBS.php b/samples/Financial1/COUPDAYBS.php deleted file mode 100644 index 4405a1fc0d..0000000000 --- a/samples/Financial1/COUPDAYBS.php +++ /dev/null @@ -1,29 +0,0 @@ -log('Returns the number of days from the beginning of a coupon\'s period to the settlement date.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPDAYBS(B1, B2, B3)'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPDAYBS() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/COUPDAYS.php b/samples/Financial1/COUPDAYS.php deleted file mode 100644 index 4f94ccf9a3..0000000000 --- a/samples/Financial1/COUPDAYS.php +++ /dev/null @@ -1,29 +0,0 @@ -log('Returns the number of days in the coupon period that contains the settlement date.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPDAYS(B1, B2, B3)'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPDAYS() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/COUPDAYSNC.php b/samples/Financial1/COUPDAYSNC.php deleted file mode 100644 index 851a010350..0000000000 --- a/samples/Financial1/COUPDAYSNC.php +++ /dev/null @@ -1,29 +0,0 @@ -log('Returns the number of days from the settlement date to the next coupon date.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPDAYSNC(B1, B2, B3)'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPDAYSNC() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/COUPNCD.php b/samples/Financial1/COUPNCD.php deleted file mode 100644 index 1311716d8e..0000000000 --- a/samples/Financial1/COUPNCD.php +++ /dev/null @@ -1,30 +0,0 @@ -log('Returns the next coupon date, after the settlement date.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPNCD(B1, B2, B3)'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPNCD() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/COUPNUM.php b/samples/Financial1/COUPNUM.php deleted file mode 100644 index 255aea2951..0000000000 --- a/samples/Financial1/COUPNUM.php +++ /dev/null @@ -1,30 +0,0 @@ -log('Returns the number of coupons payable, between a security\'s settlement date and maturity date,'); -$helper->log('rounded up to the nearest whole coupon.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPNUM(B1, B2, B3)'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPNUM() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/COUPPCD.php b/samples/Financial1/COUPPCD.php deleted file mode 100644 index 0465821ce5..0000000000 --- a/samples/Financial1/COUPPCD.php +++ /dev/null @@ -1,30 +0,0 @@ -log('Returns the previous coupon date, before the settlement date for a security.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Jan-2011')], - ['Maturity Date', DateHelper::getDateValue('25-Oct-2012')], - ['Frequency', 4], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -// Now the formula -$worksheet->setCellValue('B6', '=COUPPCD(B1, B2, B3)'); -$worksheet->getStyle('B6')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); - -$helper->log($worksheet->getCell('B6')->getValue()); -$helper->log('COUPPCD() Result is ' . $worksheet->getCell('B6')->getFormattedValue()); diff --git a/samples/Financial1/CUMIPMT.php b/samples/Financial1/CUMIPMT.php deleted file mode 100644 index 45331cf9b4..0000000000 --- a/samples/Financial1/CUMIPMT.php +++ /dev/null @@ -1,38 +0,0 @@ -log('Returns the cumulative interest paid on a loan or investment, between two specified periods.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate (per period)', 0.05 / 12], - ['Number of Periods', 5 * 12], - ['Present Value', 50000], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 5; -for ($year = 1; $year <= 5; ++$year) { - $row = (string) ($baseRow + $year); - $yearStartPeriod = (int) $year * 12 - 11; - $yearEndPeriod = (int) $year * 12; - - $worksheet->setCellValue("A{$row}", "Yr {$year}"); - $worksheet->setCellValue("B{$row}", "=CUMIPMT(\$B\$1, \$B\$2, \$B\$3, {$yearStartPeriod}, {$yearEndPeriod}, 0)"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("CUMIPMT() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial1/CUMPRINC.php b/samples/Financial1/CUMPRINC.php deleted file mode 100644 index fee1eaa246..0000000000 --- a/samples/Financial1/CUMPRINC.php +++ /dev/null @@ -1,38 +0,0 @@ -log('Returns the cumulative payment on the principal of a loan or investment, between two specified periods.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate (per period)', 0.05 / 12], - ['Number of Periods', 5 * 12], - ['Present Value', 50000], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 5; -for ($year = 1; $year <= 5; ++$year) { - $row = (string) ($baseRow + $year); - $yearStartPeriod = (int) $year * 12 - 11; - $yearEndPeriod = (int) $year * 12; - - $worksheet->setCellValue("A{$row}", "Yr {$year}"); - $worksheet->setCellValue("B{$row}", "=CUMPRINC(\$B\$1, \$B\$2, \$B\$3, {$yearStartPeriod}, {$yearEndPeriod}, 0)"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("CUMPRINC() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/DB.php b/samples/Financial2/DB.php deleted file mode 100644 index b615585c2a..0000000000 --- a/samples/Financial2/DB.php +++ /dev/null @@ -1,50 +0,0 @@ -log('Returns the depreciation of an asset, using the Fixed Declining Balance Method,'); -$helper->log('for each period of the asset\'s lifetime.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Cost Value', 10000], - ['Salvage', 1000], - ['Life', 5, 'Years'], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 5; -for ($year = 1; $year <= 5; ++$year) { - $row = (string) ($baseRow + $year); - - $worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}"); - $worksheet->setCellValue("B{$row}", "=DB(\$B\$1, \$B\$2, \$B\$3, {$year})"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("DB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} - -$helper->log('And with depreciation only starting after 6 months.'); - -$baseRow = 12; -for ($year = 1; $year <= 6; ++$year) { - $row = (string) ($baseRow + $year); - - $worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}"); - $worksheet->setCellValue("B{$row}", "=DB(\$B\$1, \$B\$2, \$B\$3, {$year}, 6)"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("DB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/DDB.php b/samples/Financial2/DDB.php deleted file mode 100644 index a00268a950..0000000000 --- a/samples/Financial2/DDB.php +++ /dev/null @@ -1,36 +0,0 @@ -log('Returns the depreciation of an asset, using the Double Declining Balance Method,'); -$helper->log('for each period of the asset\'s lifetime.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Cost Value', 10000], - ['Salvage', 1000], - ['Life', 5, 'Years'], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 5; -for ($year = 1; $year <= 5; ++$year) { - $row = (string) ($baseRow + $year); - - $worksheet->setCellValue("A{$row}", "Depreciation after Yr {$year}"); - $worksheet->setCellValue("B{$row}", "=DDB(\$B\$1, \$B\$2, \$B\$3, {$year})"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("DDB() Year {$year} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/DISC.php b/samples/Financial2/DISC.php deleted file mode 100644 index 2da3e0324e..0000000000 --- a/samples/Financial2/DISC.php +++ /dev/null @@ -1,32 +0,0 @@ -log('Returns the Discount Rate for a security.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Apr-2016')], - ['Maturity Date', DateHelper::getDateValue('31-Mar-2021')], - ['Par Value', 95.00], - ['Redemption Value', 100.00], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B3:B4')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B7', '=DISC(B1, B2, B3, B4)'); -$worksheet->getStyle('B7')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('B7')->getValue()); -$helper->log('DISC() Result is ' . $worksheet->getCell('B7')->getFormattedValue()); diff --git a/samples/Financial2/DOLLARDE.php b/samples/Financial2/DOLLARDE.php deleted file mode 100644 index 3282a82494..0000000000 --- a/samples/Financial2/DOLLARDE.php +++ /dev/null @@ -1,30 +0,0 @@ -log('Returns the dollar value in fractional notation, into a dollar value expressed as a decimal.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - [1.01, 16], - [1.1, 16], - [1.03, 32], - [1.3, 32], - [1.12, 32], -]; - -$worksheet->fromArray($arguments, null, 'A1'); - -// Now the formula -for ($row = 1; $row <= 5; ++$row) { - $worksheet->setCellValue("C{$row}", "=DOLLARDE(A{$row}, B{$row})"); - - $helper->log($worksheet->getCell("C{$row}")->getValue()); - $helper->log('DOLLARDE() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/DOLLARFR.php b/samples/Financial2/DOLLARFR.php deleted file mode 100644 index 9a4185e51b..0000000000 --- a/samples/Financial2/DOLLARFR.php +++ /dev/null @@ -1,30 +0,0 @@ -log('Returns the dollar value expressed as a decimal number, into a dollar price, expressed as a fraction.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - [1.0625, 16], - [1.625, 16], - [1.09375, 32], - [1.9375, 32], - [1.375, 32], -]; - -$worksheet->fromArray($arguments, null, 'A1'); - -// Now the formula -for ($row = 1; $row <= 5; ++$row) { - $worksheet->setCellValue("C{$row}", "=DOLLARFR(A{$row}, B{$row})"); - - $helper->log($worksheet->getCell("C{$row}")->getValue()); - $helper->log('DOLLARFR() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/EFFECT.php b/samples/Financial2/EFFECT.php deleted file mode 100644 index 263a964b86..0000000000 --- a/samples/Financial2/EFFECT.php +++ /dev/null @@ -1,31 +0,0 @@ -log('Returns the effective annual interest rate for a given nominal interest rate and number of'); -$helper->log('compounding periods per year.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - [0.10, 4], - [0.10, 2], - [0.025, 2], -]; - -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -for ($row = 1; $row <= 3; ++$row) { - $worksheet->setCellValue("C{$row}", "=EFFECT(A{$row}, B{$row})"); - $worksheet->getStyle("C{$row}")->getNumberFormat()->setFormatCode('0.00%'); - - $helper->log($worksheet->getCell("C{$row}")->getValue()); - $helper->log('EFFECT() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue()); -} diff --git a/samples/Financial2/FV.php b/samples/Financial2/FV.php deleted file mode 100644 index b89dc8b0a1..0000000000 --- a/samples/Financial2/FV.php +++ /dev/null @@ -1,36 +0,0 @@ -log('Returns the Future Value of an investment with periodic constant payments and a constant interest rate.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate', 0.05, 0.10], - ['Pament Frequency', 12, 4], - ['Duration (Years)', 5, 4], - ['Investment', -1000.00, -2000.00], - ['Payment Type', 0, 1], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B4:C4')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B8', '=FV(B1/B2, B3*B2, B4)'); -$worksheet->setCellValue('C8', '=FV(C1/C2, C3*C2, C4, null, C5)'); -$worksheet->getStyle('B8:C8')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B8')->getValue()); -$helper->log('FV() Result is ' . $worksheet->getCell('B8')->getFormattedValue()); - -$helper->log($worksheet->getCell('C8')->getValue()); -$helper->log('FV() Result is ' . $worksheet->getCell('C8')->getFormattedValue()); diff --git a/samples/Financial2/FVSCHEDULE.php b/samples/Financial2/FVSCHEDULE.php deleted file mode 100644 index eab984dba0..0000000000 --- a/samples/Financial2/FVSCHEDULE.php +++ /dev/null @@ -1,36 +0,0 @@ -log('Returns the Future Value of an initial principal, after applying a series of compound interest rates.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Principal'], - [10000.00], - [null], - ['Schedule'], - [0.05], - [0.05], - [0.035], - [0.035], - [0.035], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('A2')->getNumberFormat()->setFormatCode('$#,##0.00'); -$worksheet->getStyle('A5:A9')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -$worksheet->setCellValue('B1', '=FVSCHEDULE(A2, A5:A9)'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B1')->getValue()); -$helper->log('FVSCHEDULE() Result is ' . $worksheet->getCell('B1')->getFormattedValue()); diff --git a/samples/Financial3/INTRATE.php b/samples/Financial3/INTRATE.php deleted file mode 100644 index 3c836e4f2b..0000000000 --- a/samples/Financial3/INTRATE.php +++ /dev/null @@ -1,32 +0,0 @@ -log('Returns the interest rate for a fully invested security.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Settlement Date', DateHelper::getDateValue('01-Apr-2005')], - ['Maturity Date', DateHelper::getDateValue('31-Mar-2010')], - ['Investment', 1000.00], - ['Investment', 2125.00], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B2')->getNumberFormat()->setFormatCode('dd-mmm-yyyy'); -$worksheet->getStyle('B3:B4')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B7', '=INTRATE(B1, B2, B3, B4)'); -$worksheet->getStyle('B7')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('B7')->getValue()); -$helper->log('INTRATE() Result is ' . $worksheet->getCell('B7')->getFormattedValue()); diff --git a/samples/Financial3/IPMT.php b/samples/Financial3/IPMT.php deleted file mode 100644 index e0c88a028b..0000000000 --- a/samples/Financial3/IPMT.php +++ /dev/null @@ -1,37 +0,0 @@ -log('Returns the interest payment, during a specific period of a loan or investment that is paid in,'); -$helper->log('constant periodic payments, with a constant interest rate.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate', 0.05], - ['Number of Years', 5], - ['Present Value', 50000.00], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 6; -for ($month = 1; $month <= 12; ++$month) { - $row = (string) ($baseRow + $month); - - $worksheet->setCellValue("A{$row}", "Payment for Mth {$month}"); - $worksheet->setCellValue("B{$row}", "=IPMT(\$B\$1/12, {$month}, \$B\$2*12, \$B\$3)"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("IPMT() Month {$month} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial3/IRR.php b/samples/Financial3/IRR.php deleted file mode 100644 index 461f583d3c..0000000000 --- a/samples/Financial3/IRR.php +++ /dev/null @@ -1,38 +0,0 @@ -log('Returns the Internal Rate of Return for a supplied series of periodic cash flows.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Initial Investment', -100.00], - ['Year 1 Income', 20.00], - ['Year 2 Income', 24.00, 'IRR after 3 Years'], - ['Year 3 Income', 28.80], - ['Year 4 Income', 34.56, 'IRR after 5 Years'], - ['Year 5 Income', 41.47], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B6')->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('C4', '=IRR(B1:B4)'); -$worksheet->getStyle('C4')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('C4')->getValue()); -$helper->log('IRR() Result is ' . $worksheet->getCell('C4')->getFormattedValue()); - -$worksheet->setCellValue('C6', '=IRR(B1:B6)'); -$worksheet->getStyle('C6')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('C6')->getValue()); -$helper->log('IRR() Result is ' . $worksheet->getCell('C6')->getFormattedValue()); diff --git a/samples/Financial3/ISPMT.php b/samples/Financial3/ISPMT.php deleted file mode 100644 index 86a95ca848..0000000000 --- a/samples/Financial3/ISPMT.php +++ /dev/null @@ -1,36 +0,0 @@ -log('Returns the interest paid during a specific period of a loan or investment.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate', 0.05], - ['Number of Years', 5], - ['Present Value', 50000.00], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B3')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$baseRow = 6; -for ($month = 1; $month <= 12; ++$month) { - $row = (string) ($baseRow + $month); - - $worksheet->setCellValue("A{$row}", "Payment for Mth {$month}"); - $worksheet->setCellValue("B{$row}", "=ISPMT(\$B\$1/12, {$month}, \$B\$2*12, \$B\$3)"); - $worksheet->getStyle("B{$row}")->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); - - $helper->log($worksheet->getCell("B{$row}")->getValue()); - $helper->log("ISPMT() Month {$month} Result is " . $worksheet->getCell("B{$row}")->getFormattedValue()); -} diff --git a/samples/Financial3/MIRR.php b/samples/Financial3/MIRR.php deleted file mode 100644 index 57fefe042a..0000000000 --- a/samples/Financial3/MIRR.php +++ /dev/null @@ -1,42 +0,0 @@ -log('Returns the Modified Internal Rate of Return for a supplied series of periodic cash flows.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Initial Investment', -100.00], - ['Year 1 Income', 18.00], - ['Year 2 Income', 22.50, 'MIRR after 3 Years'], - ['Year 3 Income', 28.00], - ['Year 4 Income', 35.50, 'MIRR after 5 Years'], - ['Year 5 Income', 45.00], - [null], - ['Finance Rate', 0.055], - ['Re-invest Rate', 0.05], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B6')->getNumberFormat()->setFormatCode('$#,##0.00;-$#,##0.00'); -$worksheet->getStyle('B8:B9')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -$worksheet->setCellValue('C4', '=MIRR(B1:B4, B8, B9)'); -$worksheet->getStyle('C4')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('C4')->getValue()); -$helper->log('MIRR() Result is ' . $worksheet->getCell('C4')->getFormattedValue()); - -$worksheet->setCellValue('C6', '=MIRR(B1:B6, B8, B9)'); -$worksheet->getStyle('C6')->getNumberFormat()->setFormatCode('0.00%'); - -$helper->log($worksheet->getCell('C6')->getValue()); -$helper->log('MIRR() Result is ' . $worksheet->getCell('C6')->getFormattedValue()); diff --git a/samples/Financial3/NOMINAL.php b/samples/Financial3/NOMINAL.php deleted file mode 100644 index d1904b3fd3..0000000000 --- a/samples/Financial3/NOMINAL.php +++ /dev/null @@ -1,31 +0,0 @@ -log('Returns the nominal interest rate for a given effective interest rate and number of'); -$helper->log('compounding periods per year.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - [0.10, 4], - [0.10, 2], - [0.025, 12], -]; - -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:B3')->getNumberFormat()->setFormatCode('0.00%'); - -// Now the formula -for ($row = 1; $row <= 3; ++$row) { - $worksheet->setCellValue("C{$row}", "=NOMINAL(A{$row}, B{$row})"); - $worksheet->getStyle("C{$row}")->getNumberFormat()->setFormatCode('0.00%'); - - $helper->log($worksheet->getCell("C{$row}")->getValue()); - $helper->log('NOMINAL() Result is ' . $worksheet->getCell("C{$row}")->getFormattedValue()); -} diff --git a/samples/Financial3/NPER.php b/samples/Financial3/NPER.php deleted file mode 100644 index fcd6ce0950..0000000000 --- a/samples/Financial3/NPER.php +++ /dev/null @@ -1,39 +0,0 @@ -log('Returns the number of periods required to pay off a loan, for a constant periodic payment'); -$helper->log('and a constant interest rate.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Interest Rate', 0.04, 0.06], - ['Payments per Year', 1, 4], - ['Payment Amount', -6000.00, -2000], - ['Present Value', 50000, 60000], - ['Future Value', null, 30000], - ['Payment Type', null, FinancialConstants::PAYMENT_BEGINNING_OF_PERIOD], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B3:C5')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -$worksheet->setCellValue('B8', '=NPER(B1/B2, B3, B4)'); - -$helper->log($worksheet->getCell('B8')->getValue()); -$helper->log('NPER() Result is ' . $worksheet->getCell('B8')->getFormattedValue()); - -$worksheet->setCellValue('C8', '=NPER(C1/C2, C3, C4, C5, C6)'); - -$helper->log($worksheet->getCell('C8')->getValue()); -$helper->log('NPER() Result is ' . $worksheet->getCell('C8')->getFormattedValue()); diff --git a/samples/Financial3/NPV.php b/samples/Financial3/NPV.php deleted file mode 100644 index 39759d09ec..0000000000 --- a/samples/Financial3/NPV.php +++ /dev/null @@ -1,43 +0,0 @@ -log('Returns the Net Present Value of an investment, based on a supplied discount rate,'); -$helper->log('and a series of future payments and income.'); - -// Create new PhpSpreadsheet object -$spreadsheet = new Spreadsheet(); -$worksheet = $spreadsheet->getActiveSheet(); - -// Add some data -$arguments = [ - ['Annual Discount Rate', 0.02, 0.05], - ['Initial Investment Cost', -5000.00, -10000], - ['Return from Year 1', 800.00, 2000.00], - ['Return from Year 2', 950.00, 2400.00], - ['Return from Year 3', 1080.00, 2900.00], - ['Return from Year 4', 1220.00, 3500.00], - ['Return from Year 5', 1500.00, 4100.00], -]; - -// Some basic formatting for the data -$worksheet->fromArray($arguments, null, 'A1'); -$worksheet->getStyle('B1:C1')->getNumberFormat()->setFormatCode('0.00%'); -$worksheet->getStyle('B2:C7')->getNumberFormat()->setFormatCode('$#,##0.00'); - -// Now the formula -// When initial investment is made at the end of the first period -$worksheet->setCellValue('B10', '=NPV(B1, B2:B7)'); -$worksheet->getStyle('B10')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('B10')->getValue()); -$helper->log('NPV() Result is ' . $worksheet->getCell('B10')->getFormattedValue()); - -// When initial investment is made at the start of the first period -$worksheet->setCellValue('C10', '=NPV(C1, C3:C7) + C2'); -$worksheet->getStyle('C10')->getNumberFormat()->setFormatCode('$#,##0.00'); - -$helper->log($worksheet->getCell('C10')->getValue()); -$helper->log('NPV() Result is ' . $worksheet->getCell('C10')->getFormattedValue()); diff --git a/samples/Header.php b/samples/Header.php index 6707768514..fb8bd986eb 100644 --- a/samples/Header.php +++ b/samples/Header.php @@ -1,14 +1,12 @@ - -
- ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/samples/bootstrap/js/jquery.min.js b/samples/bootstrap/js/jquery.min.js index c4c6022f29..f6a6a99e60 100644 --- a/samples/bootstrap/js/jquery.min.js +++ b/samples/bootstrap/js/jquery.min.js @@ -1,2 +1,4 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"label"in b&&b.disabled===a||"form"in b&&b.disabled===a||"form"in b&&b.disabled===!1&&(b.isDisabled===a||b.isDisabled!==!a&&("label"in b||!ea(b))!==a)}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(_,aa),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=V.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(_,aa),$.test(j[0].type)&&qa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&sa(j),!a)return G.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||$.test(a)&&qa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){if(r.isFunction(b))return r.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return r.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(C.test(b))return r.filter(b,a,c);b=r.filter(b,a)}return r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType})}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/\S+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0, +r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ja=/^$|\/(?:java|ecma)script/i,ka={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ka.optgroup=ka.option,ka.tbody=ka.tfoot=ka.colgroup=ka.caption=ka.thead,ka.th=ka.td;function la(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function ma(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=la(l.appendChild(f),"script"),j&&ma(g),c){k=0;while(f=g[k++])ja.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var pa=d.documentElement,qa=/^key/,ra=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,sa=/^([^.]*)(?:\.(.+)|)/;function ta(){return!0}function ua(){return!1}function va(){try{return d.activeElement}catch(a){}}function wa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)wa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ua;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(pa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=sa.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c-1:r.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h\x20\t\r\n\f]*)[^>]*)\/>/gi,ya=/\s*$/g;function Ca(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Da(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ea(a){var b=Aa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&za.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(m&&(e=oa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(la(e,"script"),Da),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=la(h),f=la(a),d=0,e=f.length;d0&&ma(g,!i&&la(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(la(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!ya.test(a)&&!ka[(ia.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Xa(a,b,c,d,e){return new Xa.prototype.init(a,b,c,d,e)}r.Tween=Xa,Xa.prototype={constructor:Xa,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Xa.propHooks[this.prop];return a&&a.get?a.get(this):Xa.propHooks._default.get(this)},run:function(a){var b,c=Xa.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Xa.propHooks._default.set(this),this}},Xa.prototype.init.prototype=Xa.prototype,Xa.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Xa.propHooks.scrollTop=Xa.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Xa.prototype.init,r.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=/queueHooks$/;function ab(){Za&&(a.requestAnimationFrame(ab),r.fx.tick())}function bb(){return a.setTimeout(function(){Ya=void 0}),Ya=r.now()}function cb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=aa[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function db(a,b,c){for(var d,e=(gb.tweeners[b]||[]).concat(gb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?hb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K); +if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),hb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ib[b]||r.find.attr;ib[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ib[g],ib[g]=e,e=null!=c(a,b,d)?g:null,ib[g]=f),e}});var jb=/^(?:input|select|textarea|button)$/i,kb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):jb.test(a.nodeName)||kb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});var lb=/[\t\r\n\f]/g;function mb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,mb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,mb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=mb(c),d=1===c.nodeType&&(" "+e+" ").replace(lb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=r.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,mb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=mb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(c)+" ").replace(lb," ").indexOf(b)>-1)return!0;return!1}});var nb=/\r/g,ob=/[\x20\t\r\n\f]+/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(nb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:r.trim(r.text(a)).replace(ob," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ha.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,""),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("'; - $scriptSingle = new RichText(); - $scriptSingle->createText($scriptTextSingle); - - return [ - 'single line plain text' => [$plainSingle, '
' - . 'I am comment.
' . PHP_EOL - . 'Comment'], - 'multi-line plain text' => [$plainMulti, '
' - . 'I am
' . PHP_EOL - . 'multi-line
' . PHP_EOL - . 'comment.
' . PHP_EOL - . 'Comment'], - 'single line simple rich text' => [$richSingle, '
' - . "I am comment.
" . PHP_EOL - . 'Comment'], - 'multi-line simple rich text' => [$richMultiSimple, '
' - . "I am
" . PHP_EOL - . 'multi-line
' . PHP_EOL - . 'comment.
' . PHP_EOL - . 'Comment'], - 'multi-line mixed rich text' => [$richMultiMixed, '
I am
' . PHP_EOL - . "multi-line
" . PHP_EOL - . 'comment!
' . PHP_EOL - . 'Comment'], - 'script single' => [$scriptSingle, '
' - . 'I am <script>alert("Hello")</script>
' . PHP_EOL - . 'Comment'], - ]; - } - - #[DataProvider('providerCommentRichText')] - public function testComments(RichText $richText, string $expected): void - { - $spreadsheet = new Spreadsheet(); - - $spreadsheet->getActiveSheet() - ->getCell('A1') - ->setValue('Comment'); - - $spreadsheet->getActiveSheet() - ->getComment('A1') - ->setText($richText); - $writer = new Html($spreadsheet); - $output = $writer->generateHtmlAll(); - self::assertStringContainsString($expected, $output); - - $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - - $actual = $reloadedSpreadsheet->getActiveSheet()->getComment('A1')->getText()->getPlainText(); - self::assertSame($richText->getPlainText(), $actual); - $reloadedSpreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlConditionalFormattingTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlConditionalFormattingTest.php deleted file mode 100644 index c5a31e415c..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlConditionalFormattingTest.php +++ /dev/null @@ -1,65 +0,0 @@ -load($file); - $writer = new HtmlWriter($spreadsheet); - $writer->setConditionalFormatting(true); - $this->data = $writer->generateHtmlAll(); - $spreadsheet->disconnectWorksheets(); - } - - private function extractCell(string $coordinate): string - { - [$column, $row] = Coordinate::indexesFromString($coordinate); - --$column; - --$row; - // extract row into $matches - $match = preg_match('~~s', $this->data, $matches); - if ($match !== 1) { - return 'unable to match row'; - } - $rowData = $matches[0]; - // extract cell into $matches - $match = preg_match('~Jan<', 'no conditional styling for B1'], - ['F2', 'background-color:#C6EFCE;">120<', 'conditional style for F2'], - ['H2', 'background-color:#FFEB9C;">90<', 'conditional style for H2'], - ['F3', 'background-color:#C6EFCE;">70<', 'conditional style for cell F3'], - ['H3', 'background-color:#FFEB9C;">60<', 'conditional style for cell H3'], - ['F4', 'background-color:#C6EFCE;">1<', 'conditional style for cell F4'], - ['L4', 'background-color:#FFC7CE;">5<', 'conditional style for cell L4'], - ['F5', 'class="column5 style1 n">0<', 'no conditional styling for F5'], - ]; - foreach ($expectedMatches as $expected) { - [$coordinate, $expectedString, $message] = $expected; - $string = $this->extractCell($coordinate); - self::assertStringContainsString($expectedString, $string, $message); - } - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlDifferentConditionalFormattingsTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlDifferentConditionalFormattingsTest.php deleted file mode 100644 index 4bdb886210..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlDifferentConditionalFormattingsTest.php +++ /dev/null @@ -1,94 +0,0 @@ -load($file); - $writer = new HtmlWriter($spreadsheet); - $writer->setConditionalFormatting(true); - $this->data = $writer->generateHtmlAll(); - $spreadsheet->disconnectWorksheets(); - } - - private function extractCell(string $coordinate): string - { - [$column, $row] = Coordinate::indexesFromString($coordinate); - --$column; - --$row; - // extract row into $matches - $match = preg_match('~~s', $this->data, $matches); - if ($match !== 1) { - return 'unable to match row'; - } - $rowData = $matches[0]; - // extract cell into $matches - $match = preg_match('~1<', 'A1 equals hit'], - ['B1', 'class="column1 style1 n">2<', 'B1 equals miss'], - ['E1', 'background-color:#B7E1CD;">1<', 'E1 equals horizontal reference hit'], - ['F1', 'class="column5 style1 n">2<', 'F1 equals horizontal reference miss'], - ['G1', 'class="column6 style1 n">3<', 'G1 equals horizontal reference miss'], - ['A2', 'background-color:#B7E1CD;">terve<', 'A2 text contains hit'], - ['B2', 'class="column1 style1 s">moi<', 'B2 text contains miss'], - ['A3', 'background-color:#B7E1CD;">terve<', 'A3 text does not contain hit'], - ['B3', 'class="column1 style1 s">moi<', 'B2 text does not contain miss'], - ['A4', 'background-color:#B7E1CD;">terve<', 'A4 text starts with hit'], - ['B4', 'class="column1 style1 s">moi<', 'B2 text starts with miss'], - ['A5', 'background-color:#B7E1CD;">terve<', 'A5 text ends with hit'], - ['B5', 'class="column1 style1 s">moi<', 'B5 text ends with miss'], - ['A6', 'background-color:#B7E1CD;">2025/01/01<', 'A6 date after hit'], - ['B6', 'class="column1 style2 n">2020/01/01<', 'B6 date after miss'], - ['A7', 'background-color:#B7E1CD;">terve vaan<', 'A7 text contains hit'], - ['B7', 'class="column1 style1 s">moi<', 'B7 text contains miss'], - ['A8', 'background-color:#B7E1CD;">terve<', 'A8 text does not contain hit'], - ['B8', 'class="column1 style1 s">terve vaan<', 'B2 does not contain miss'], - ['A9', 'background-color:#B7E1CD;">#DIV/0!<', 'A10 own formula is error hit'], - ['B9', 'class="column1 style1 s">moi<', 'B9 own formula is error miss'], - ['A10', 'background-color:#B7E1CD;">moi<', 'A10 own formula is not error hit'], - ['B10', 'class="column1 style3 s">#DIV/0!<', 'B10 own formula is not error miss'], - ['A11', 'background-color:#B7E1CD;">terve<', 'A11 own formula count instances of cell on line and hit when more than one hit'], - ['B11', 'background-color:#B7E1CD;">terve<', 'B11 own formula count instances of cell on line and hit when more than one hit'], - ['C11', 'class="column2 style1 s">moi<', 'C11 own formula count instances of cell on line and hit when more than one miss'], - ['A12', 'background-color:#B7E1CD;">moi<', 'A12 own formula count instances of cell on line and hit when at most 1 hit'], - ['B12', 'class="column1 style1 s">terve<', 'B12 own formula count instances of cell on line and hit when at most 1 miss'], - ['C12', 'class="column2 style1 s">terve<', 'C11 own formula count instances of cell on line and hit when at most 1 miss'], - ['A13', 'background-color:#B7E1CD;">12<', 'A13 own formula self reference hit'], - ['B13', 'class="column1 style1 n">10<', 'B13 own formula self reference miss'], - ['A14', 'background-color:#B7E1CD;">10<', 'A14 multiple conditional hits'], - ['B14', 'class="column1 style1 n">1<', 'B14 multiple conditionals miss'], - ['F7', 'background-color:#B7E1CD;">1<', 'F7 equals vertical reference hit'], - ['F8', 'class="column5 style1 n">2<', 'F8 equals vertical reference miss'], - ['F9', 'class="column5 style1 n">3<', 'F9 equals vertical reference miss'], - ['F10', 'class="column5 style1 n">4<', 'F10 equals vertical reference miss'], - ]; - foreach ($expectedMatches as $expected) { - [$coordinate, $expectedString, $message] = $expected; - $string = $this->extractCell($coordinate); - self::assertStringContainsString($expectedString, $string, $message); - } - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlNumberFormatTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlNumberFormatTest.php deleted file mode 100644 index 6044b1d2bb..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlNumberFormatTest.php +++ /dev/null @@ -1,218 +0,0 @@ -getActiveSheet(); - $sheet->setCellValue('A1', -50); - $sheet->setCellValue('A2', 3000); - $sheet->setCellValue('A3', 0); - $sheet->setCellValue('A4', '
'); - $fmt = '[Blue]$#,##0;[Red]$#,##0;$#,##0'; - $sheet->getStyle('A1:A4')->getNumberFormat()->setFormatCode($fmt); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - - $tabl = $divs->item(0)?->getElementsByTagName('table'); - $tbod = $tabl?->item(0)?->getElementsByTagName('tbody'); - $rows = $tbod?->item(0)?->getElementsByTagName('tr'); - self::assertCount(4, $rows); - - $tds = $rows?->item(0)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(1, $spans); - $style = $spans?->item(0)?->getAttribute('style'); - self::assertSame(1, preg_match('/color:red/', "$style")); - self::assertSame('$50', $spans?->item(0)?->textContent); - - $tds = $rows?->item(1)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(1, $spans); - $style = $spans?->item(0)?->getAttribute('style'); - self::assertSame(1, preg_match('/color:blue/', "$style")); - self::assertSame('$3,000', $spans?->item(0)?->textContent); - - $tds = $rows?->item(2)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(0, $spans); - self::assertSame('$0', $tds?->item(0)?->textContent); - - $tds = $rows?->item(3)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(0, $spans); - self::assertEquals('
', $tds?->item(0)?->textContent); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - public function testColorNumberFormatComplex(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', -50); - $sheet->setCellValue('A2', 3000.75); - $sheet->setCellValue('A3', 0); - $sheet->setCellValue('A4', 3000.25); - $fmt = '[Blue][>=3000.5]$#,##0.00;[Red][<0]$#,##0.00;$#,##0.00'; - $sheet->getStyle('A1:A4')->getNumberFormat()->setFormatCode($fmt); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - - $tabl = $divs->item(0)?->getElementsByTagName('table'); - $tbod = $tabl?->item(0)?->getElementsByTagName('tbody'); - $rows = $tbod?->item(0)?->getElementsByTagName('tr'); - self::assertCount(4, $rows); - - $tds = $rows?->item(0)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(1, $spans); - $style = $spans?->item(0)?->getAttribute('style'); - self::assertSame(1, preg_match('/color:red/', "$style")); - self::assertSame('$50.00', $spans?->item(0)?->textContent); - - $tds = $rows?->item(1)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(1, $spans); - $style = $spans?->item(0)?->getAttribute('style'); - self::assertSame(1, preg_match('/color:blue/', "$style")); - self::assertSame('$3,000.75', $spans?->item(0)?->textContent); - - $tds = $rows?->item(2)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(0, $spans); - self::assertSame('$0.00', $tds?->item(0)?->textContent); - - $tds = $rows?->item(3)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $spans = $tds?->item(0)?->getElementsByTagName('span'); - self::assertCount(0, $spans); - self::assertSame('$3,000.25', $tds?->item(0)?->textContent); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - #[DataProvider('numberFormatProvider')] - public function testFormatValueWithMask(mixed $expectedResult, mixed $val, string $fmt): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->getCell('A1')->setValue($val)->getStyle()->getNumberFormat()->setFormatCode($fmt); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - - $tabl = $divs->item(0)?->getElementsByTagName('table'); - $tbod = $tabl?->item(0)?->getElementsByTagName('tbody'); - $rows = $tbod?->item(0)?->getElementsByTagName('tr'); - - $tds = $rows?->item(0)?->getElementsByTagName('td'); - $nbsp = html_entity_decode(' ', Settings::htmlEntityFlags()); - self::assertEquals($expectedResult, str_replace($nbsp, ' ', (string) $tds?->item(0)?->textContent)); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - /** @return mixed[] */ - public static function numberFormatProvider(): array - { - /** @var mixed[] */ - $retVal = require __DIR__ . '/../../../data/Style/NumberFormat.php'; - - return $retVal; - } - - #[DataProvider('numberFormatDatesProvider')] - public function testFormatValueWithMaskDate(mixed $expectedResult, mixed $val, string $fmt): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->getCell('A1')->setValue($val)->getStyle()->getNumberFormat()->setFormatCode($fmt); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - - $tabl = $divs->item(0)?->getElementsByTagName('table'); - $tbod = $tabl?->item(0)?->getElementsByTagName('tbody'); - $rows = $tbod?->item(0)?->getElementsByTagName('tr'); - - $tds = $rows?->item(0)?->getElementsByTagName('td'); - $nbsp = html_entity_decode(' ', Settings::htmlEntityFlags()); - self::assertSame($expectedResult, str_replace($nbsp, ' ', (string) $tds?->item(0)?->textContent)); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - /** @return mixed[] */ - public static function numberFormatDatesProvider(): array - { - /** @var mixed[] */ - $retVal = require __DIR__ . '/../../../data/Style/NumberFormatDates.php'; - - return $retVal; - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatTest.php deleted file mode 100644 index c78dda2591..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatTest.php +++ /dev/null @@ -1,64 +0,0 @@ -load($file); - $writer = new HtmlWriter($spreadsheet); - $writer->setTableFormats(true); - $this->data = $writer->generateHtmlAll(); - $spreadsheet->disconnectWorksheets(); - } - - private function extractCell(string $coordinate): string - { - [$column, $row] = Coordinate::indexesFromString($coordinate); - --$column; - --$row; - // extract row into $matches - $match = preg_match('~~s', $this->data, $matches); - if ($match !== 1) { - return 'unable to match row'; - } - $rowData = $matches[0]; - // extract cell into $matches - $match = preg_match('~Sep<', 'table style for header row cell J1'], - ['J2', 'background-color:#C0E4F5;">110<', 'table style for cell J2'], - ['I3', 'background-color:#82CAEB;">70<', 'table style for cell I3'], - ['J3', 'background-color:#82CAEB;">70<', 'table style for cell J3'], // as conditional calculations are off - ['K3', 'background-color:#82CAEB;">70<', 'table style for cell K3'], - ['J4', 'background-color:#C0E4F5;">1<', 'table style for cell J4'], - ['J5', 'background-color:#82CAEB;">1<', 'table style for cell J5'], - ]; - foreach ($expectedMatches as $expected) { - [$coordinate, $expectedString, $message] = $expected; - $string = $this->extractCell($coordinate); - self::assertStringContainsString($expectedString, $string, $message); - } - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatWithConditionalTest.php b/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatWithConditionalTest.php deleted file mode 100644 index 1c8a16d27e..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/HtmlTableFormatWithConditionalTest.php +++ /dev/null @@ -1,65 +0,0 @@ -load($file); - $writer = new HtmlWriter($spreadsheet); - $writer->setTableFormats(true); - $writer->setConditionalFormatting(true); - $this->data = $writer->generateHtmlAll(); - $spreadsheet->disconnectWorksheets(); - } - - private function extractCell(string $coordinate): string - { - [$column, $row] = Coordinate::indexesFromString($coordinate); - --$column; - --$row; - // extract row into $matches - $match = preg_match('~~s', $this->data, $matches); - if ($match !== 1) { - return 'unable to match row'; - } - $rowData = $matches[0]; - // extract cell into $matches - $match = preg_match('~Sep<', 'table style for header row cell J1'], - ['J2', 'background-color:#C0E4F5;">110<', 'table style for cell J2'], - ['I3', 'background-color:#82CAEB;">70<', 'table style for cell I3'], - ['J3', 'background-color:#B7E1CD;">70<', 'conditional style for cell J3'], // as conditional calculations are on - ['K3', 'background-color:#82CAEB;">70<', 'table style for cell K3'], - ['J4', 'background-color:#C0E4F5;">1<', 'table style for cell J4'], - ['J5', 'background-color:#82CAEB;">1<', 'table style for cell J5'], - ]; - foreach ($expectedMatches as $expected) { - [$coordinate, $expectedString, $message] = $expected; - $string = $this->extractCell($coordinate); - self::assertStringContainsString($expectedString, $string, $message); - } - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/ImageCopyTest.php b/tests/PhpSpreadsheetTests/Writer/Html/ImageCopyTest.php deleted file mode 100644 index ddd3200919..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/ImageCopyTest.php +++ /dev/null @@ -1,71 +0,0 @@ -xlsxFile !== '') { - unlink($this->xlsxFile); - $this->xlsxFile = ''; - } - } - - public function testImageCopyXls(): void - { - $file = 'samples/templates/27template.xls'; - $reader = new XlsReader(); - $reloadedSpreadsheet = $reader->load($file); - - $writer = new Html($reloadedSpreadsheet); - $writer->writeAllSheets(); - self::assertFalse($writer->getEmbedImages()); - $html = $writer->generateHTMLAll(); - self::assertSame(4, substr_count($html, 'writeAndReload($reloadedSpreadsheet, 'Html'); - $reloadedSpreadsheet->disconnectWorksheets(); - } - - public function testImageCopyXlsx(): void - { - $file = 'samples/templates/27template.xls'; - $reader = new XlsReader(); - $spreadsheet = $reader->load($file); - $this->xlsxFile = File::temporaryFilename(); - $writer = new XlsxWriter($spreadsheet); - $writer->save($this->xlsxFile); - $spreadsheet->disconnectWorksheets(); - $reader2 = new XlsxReader(); - $reloadedSpreadsheet = $reader2->load($this->xlsxFile); - - $writer = new Html($reloadedSpreadsheet); - $writer->writeAllSheets(); - self::assertFalse($writer->getEmbedImages()); - $html = $writer->generateHTMLAll(); - self::assertSame(4, substr_count($html, 'writeAndReload($reloadedSpreadsheet, 'Html'); - $reloadedSpreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/ImageEmbedTest.php b/tests/PhpSpreadsheetTests/Writer/Html/ImageEmbedTest.php deleted file mode 100644 index bc9e40ed4c..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/ImageEmbedTest.php +++ /dev/null @@ -1,45 +0,0 @@ -getActiveSheet(); - - $drawing = new Drawing(); - $drawing->setName('Not an image'); - $drawing->setDescription('Non-image'); - $drawing->setPath(__FILE__, false); - $drawing->setCoordinates('A1'); - $drawing->setCoordinates2('E4'); - $drawing->setWorksheet($sheet); - - $drawing = new Drawing(); - $drawing->setName('Blue Square'); - $drawing->setPath('tests/data/Writer/XLSX/blue_square.png'); - $drawing->setCoordinates('A5'); - $drawing->setCoordinates2('E8'); - $drawing->setWorksheet($sheet); - - $writer = new HtmlWriter($spreadsheet); - $writer->setEmbedImages(true); - $html = $writer->generateHTMLAll(); - self::assertSame(1, substr_count($html, 'disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/ImagesRootTest.php b/tests/PhpSpreadsheetTests/Writer/Html/ImagesRootTest.php deleted file mode 100644 index 609542d0db..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/ImagesRootTest.php +++ /dev/null @@ -1,74 +0,0 @@ -curdir = $curdir; - } - } - - protected function tearDown(): void - { - chdir($this->curdir); - } - - public function testImagesRoot(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing(); - $drawing->setName('Test'); - $drawing->setDescription('Test'); - $root = 'http://www.example.com'; - $newdir = __DIR__ . '/../../../data/Reader/HTML'; - $stub = 'image.jpg'; - $imagePath = "./$stub"; - chdir($newdir); - self::assertFileExists($imagePath); - $drawing->setPath($imagePath); - $desc = 'Test tag'; - $drawing->setDescription($desc); - $drawing->setHeight(36); - $drawing->setWorksheet($spreadsheet->getActiveSheet()); - $drawing->setCoordinates('A1'); - $sheet->setCellValue('A2', 'Image Above?'); - - $writer = new Html($spreadsheet); - $writer->setImagesRoot($root); - $html = $writer->generateHTMLAll(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - - $tabl = $divs->item(0)?->getElementsByTagName('table'); - $tbod = $tabl?->item(0)?->getElementsByTagName('tbody'); - $rows = $tbod?->item(0)?->getElementsByTagName('tr'); - self::assertCount(2, $rows); - - $tds = $rows?->item(0)?->getElementsByTagName('td'); - self::assertCount(1, $tds); - $img = $tds?->item(0)?->getElementsByTagName('img'); - self::assertCount(1, $img); - self::assertSame("$root/$stub", $img?->item(0)?->getAttribute('src')); - self::assertSame($desc, $img->item(0)->getAttribute('alt')); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/InvalidFileNameTest.php b/tests/PhpSpreadsheetTests/Writer/Html/InvalidFileNameTest.php deleted file mode 100644 index aaf3ef0fad..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/InvalidFileNameTest.php +++ /dev/null @@ -1,64 +0,0 @@ -expectException(WriterException::class); - $spreadsheet = new Spreadsheet(); - $spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1'); - $writer = new Html($spreadsheet); - $writer->save(''); - } - - public function testEmptyFileNamePdf(): void - { - $this->expectException(WriterException::class); - $spreadsheet = new Spreadsheet(); - $spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1'); - $writer = new Mpdf($spreadsheet); - $writer->save(''); - } - - public function testNotEmptyTempdirNamePdf(): void - { - $spreadsheet = new Spreadsheet(); - $spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1'); - $writer = new Mpdf($spreadsheet); - $writer->setFont('Helvetica'); - self::assertEquals('Helvetica', $writer->getFont()); - $writer->setPaperSize(PageSetup::PAPERSIZE_LEDGER); - self::assertEquals($writer->getPaperSize(), PageSetup::PAPERSIZE_LEDGER); - self::assertEquals(File::sysGetTempDir() . '/phpsppdf', $writer->getTempDir()); - $writer->setTempDir(File::sysGetTempDir()); - self::assertEquals(File::sysGetTempDir(), $writer->getTempDir()); - } - - public function testEmptyTempdirNamePdf(): void - { - $this->expectException(WriterException::class); - $spreadsheet = new Spreadsheet(); - $spreadsheet->getActiveSheet()->getCell('A1')->setValue('Cell 1'); - $writer = new Mpdf($spreadsheet); - $writer->setTempDir(''); - } - - public function testWinFileNames(): void - { - self::assertEquals('file:///C:/temp/filename.xlsx', Html::winFileToUrl('C:\temp\filename.xlsx')); - self::assertEquals('/tmp/filename.xlsx', Html::winFileToUrl('/tmp/filename.xlsx')); - self::assertEquals('a:bfile', Html::winFileToUrl('a:bfile')); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/Issue3678Test.php b/tests/PhpSpreadsheetTests/Writer/Html/Issue3678Test.php deleted file mode 100644 index e4f292c2da..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/Issue3678Test.php +++ /dev/null @@ -1,40 +0,0 @@ -getActiveSheet(); - $sheet->getCell('A1')->setValue(1); - $styleArray = [ - 'fill' => [ - 'fillType' => Fill::FILL_SOLID, - 'color' => ['rgb' => 'FFFF00'], - ], - ]; - $sheet->getStyle('A1')->applyFromArray($styleArray); - $style1 = "vertical-align:bottom; border-bottom:none #000000; border-top:none #000000; border-left:none #000000; border-right:none #000000; color:#000000; font-family:'Calibri'; font-size:11pt; background-color:#FFFF00"; - $style2 = "vertical-align:bottom; color:#000000; font-family:'Calibri'; font-size:11pt; background-color:#FFFF00"; - $style2 .= '; text-align:right; width:42pt'; - $writer = new Html($spreadsheet); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString('td.style1, th.style1 { ' . $style1 . ' }', $html); - self::assertStringContainsString('1', $html); - self::assertStringContainsString('table.sheet0 col.col0 { width:42pt }', $html); - self::assertStringContainsString('.n { text-align:right }', $html); - $writer->setUseInlineCss(true); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString('1', $html); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/LongTitleTest.php b/tests/PhpSpreadsheetTests/Writer/Html/LongTitleTest.php deleted file mode 100644 index 17e3da98f1..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/LongTitleTest.php +++ /dev/null @@ -1,36 +0,0 @@ -getProperties() - ->setTitle($title); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', 1); - - $reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - self::assertSame($expected, $reloadedSpreadsheet->getActiveSheet()->getTitle()); - $reloadedSpreadsheet->disconnectWorksheets(); - } - - public static function providerTitles(): array - { - return [ - ['Worksheet', 'This title is just a bit too long'], - ['Worksheet', 'Invalid * character'], - ['Legitimate Title', 'Legitimate Title'], - ]; - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/MailtoTest.php b/tests/PhpSpreadsheetTests/Writer/Html/MailtoTest.php deleted file mode 100644 index e9f250d37f..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/MailtoTest.php +++ /dev/null @@ -1,32 +0,0 @@ -getActiveSheet(); - $worksheet->setCellValue('A1', 'Mail Me!'); - $worksheet->getCell('A1') - ->getHyperlink() - ->setUrl('mailto:me@example.com'); - $worksheet->setCellValue('A2', 'Mail You!'); - $worksheet->getCell('A2') - ->getHyperlink() - ->setTooltip('go ahead') - ->setUrl('mailto:you@example.com'); - $writer = new HtmlWriter($spreadsheet); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString('Mail Me!', $html); - self::assertStringContainsString('Mail You!', $html); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/MemoryDrawingOffsetTest.php b/tests/PhpSpreadsheetTests/Writer/Html/MemoryDrawingOffsetTest.php deleted file mode 100644 index f30e679694..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/MemoryDrawingOffsetTest.php +++ /dev/null @@ -1,47 +0,0 @@ -getActiveSheet(); - - $image = file_get_contents(__DIR__ . '/../../../data/Reader/HTML/memoryDrawingTest.jpg'); - self::assertNotFalse($image, 'unable to read file'); - $image = imagecreatefromstring($image); - self::assertNotFalse($image, 'unable to create image from string'); - $drawing = new MemoryDrawing(); - $drawing->setImageResource($image) - ->setResizeProportional(false) //是å¦ä¿æŒæ¯”例 - ->setWidthAndHeight($w, $h) //图片宽高,原始尺寸 100*100 - ->setOffsetX($x) - ->setOffsetY($y) - ->setWorksheet($sheet); - - $writer = new Html($spreadsheet); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString('width:' . $w . 'px;left: ' . $x . 'px; top: ' . $y . 'px;position: absolute;', $html); - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); - } - - public static function dataProvider(): array - { - return [ - [33, 19, 0, 20], - [129, 110, 12, -3], - [55, 110, 33, 42], - ]; - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/NavigationBadTitleTest.php b/tests/PhpSpreadsheetTests/Writer/Html/NavigationBadTitleTest.php deleted file mode 100644 index 284fd9f4e5..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/NavigationBadTitleTest.php +++ /dev/null @@ -1,35 +0,0 @@ -getActiveSheet(); - $sheet->getCell('A1')->setValue(1); - $sheet2 = $spreadsheet->createSheet(); - $sheet2->setTitle(''); - $sheet2->getCell('A2')->setValue(2); - - $writer = new HtmlWriter($spreadsheet); - $writer->writeAllSheets(); - $html = $writer->generateHTMLAll(); - $expected = ''; - self::assertStringContainsString($expected, $html, 'appropriate characters are escaped'); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php b/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php deleted file mode 100644 index 156f9079d4..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php +++ /dev/null @@ -1,33 +0,0 @@ -getActiveSheet(); - $sheet->getCell('A1')->setValue('Click me'); - $hyperlink = new Hyperlink('http://www.example.com'); - $sheet->getCell('A1')->setHyperlink($hyperlink); - $sheet->getCell('A2')->setValue('JS link'); - $hyperlink2 = new Hyperlink('javascript:alert(\'hello1\')'); - $sheet->getCell('A2')->setHyperlink($hyperlink2); - $sheet->getCell('A3')->setValue('=HYPERLINK("javascript:alert(\'hello2\')", "jsfunc click")'); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - self::assertStringContainsString('Click me', $html, 'http hyperlink retained'); - self::assertStringContainsString('javascript:alert(\'hello1\')', $html, 'javascript hyperlink dropped'); - self::assertStringContainsString('javascript:alert(\'hello2\')', $html, 'javascript hyperlink function dropped'); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/NoTitleTest.php b/tests/PhpSpreadsheetTests/Writer/Html/NoTitleTest.php deleted file mode 100644 index 7faf8a6ad3..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/NoTitleTest.php +++ /dev/null @@ -1,62 +0,0 @@ -load($file); - self::assertSame('', $spreadsheet->getProperties()->getTitle()); - - $writer = new Html($spreadsheet); - $writer->setUseInlineCss(true); - $html = $writer->generateHTMLAll(); - self::assertStringContainsString('Sheet1', $html); - self::assertStringContainsString('C1', $html); - $writer->setUseInlineCss(false); - $html = $writer->generateHTMLAll(); - self::assertStringContainsString('C1', $html); - $spreadsheet->disconnectWorksheets(); - } - - public function testHideSomeGridlines(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->fromArray( - [ - [1, 2, 3, 4, 5, 6], - [7, 8, 9, 10, 11, 12], - [17, 18, 19, 20, 21, 22], - [27, 28, 29, 30, 31, 32], - [37, 38, 39, 40, 41, 42], - ] - ); - $sheet->getStyle('B2:D4')->getBorders()->applyFromArray( - [ - 'allBorders' => [ - 'borderStyle' => Border::BORDER_NONE, - 'color' => ['rgb' => '808080'], - ], - ], - ); - - $writer = new Html($spreadsheet); - $writer->setUseInlineCss(true); - $html = $writer->generateHTMLAll(); - self::assertStringContainsString('7', $html); - self::assertStringContainsString('19', $html); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/RepeatedRowsTest.php b/tests/PhpSpreadsheetTests/Writer/Html/RepeatedRowsTest.php deleted file mode 100644 index 321158be92..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/RepeatedRowsTest.php +++ /dev/null @@ -1,116 +0,0 @@ -getActiveSheet(); - $sheet->getPageSetup()->setRowsToRepeatAtTop([1, 2]); - $sheet->setCellValue('A1', 'Repeat1'); - $sheet->setCellValue('A2', 'Repeat2'); - for ($row = 3; $row <= 100; ++$row) { - $sheet->setCellValue("A$row", $row); - } - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLall(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - $tbl = $divs->item(0)?->getElementsByTagName('table'); - self::assertSame('', $tbl?->item(0)?->getAttribute('style')); - $thd = $divs->item(0)?->getElementsByTagName('thead'); - self::assertCount(1, $thd); - $trw = $thd?->item(0)?->getElementsByTagName('tr'); - self::assertCount(2, $trw); - $tbd = $divs->item(0)?->getElementsByTagName('tbody'); - self::assertCount(1, $tbd); - $trw = $tbd?->item(0)?->getElementsByTagName('tr'); - self::assertCount(98, $trw); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - public function testWriteNoRepeats(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - //$sheet->getPageSetup()->setRowsToRepeatAtTop([1, 2]); - $sheet->setCellValue('A1', 'Repeat1'); - $sheet->setCellValue('A2', 'Repeat2'); - for ($row = 3; $row <= 100; ++$row) { - $sheet->setCellValue("A$row", $row); - } - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLall(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - $tbl = $divs->item(0)?->getElementsByTagName('table'); - $thd = $tbl?->item(0)?->getElementsByTagName('thead'); - self::assertCount(0, $thd); - //$trw = $thd->item(0)->getElementsByTagName('tr'); - //self::assertCount(2, $trw); - $tbd = $divs->item(0)?->getElementsByTagName('tbody'); - self::assertCount(1, $tbd); - $trw = $tbd?->item(0)?->getElementsByTagName('tr'); - self::assertCount(100, $trw); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } - - public function testWriteRepeatsInline(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->getPageSetup()->setRowsToRepeatAtTop([1, 2]); - $sheet->setCellValue('A1', 'Repeat1'); - $sheet->setCellValue('A2', 'Repeat2'); - for ($row = 3; $row <= 100; ++$row) { - $sheet->setCellValue("A$row", $row); - } - - $writer = new Html($spreadsheet); - self::assertFalse($writer->getUseInlineCss()); - $writer->setUseInlineCss(true); - $html = $writer->generateHTMLall(); - $dom = new DOMDocument(); - $dom->loadHTML($html); - $body = $dom->getElementsByTagName('body')->item(0); - self::assertNotNull($body); - $divs = $body->getElementsByTagName('div'); - $tbl = $divs->item(0)?->getElementsByTagName('table'); - self::assertSame('border-collapse:collapse', $tbl?->item(0)?->getAttribute('style')); - $thd = $divs->item(0)?->getElementsByTagName('thead'); - self::assertCount(1, $thd); - $trw = $thd?->item(0)?->getElementsByTagName('tr'); - self::assertCount(2, $trw); - $tbd = $divs->item(0)?->getElementsByTagName('tbody'); - self::assertCount(1, $tbd); - $trw = $tbd?->item(0)?->getElementsByTagName('tr'); - self::assertCount(98, $trw); - - $rls = $this->writeAndReload($spreadsheet, 'Html'); - $spreadsheet->disconnectWorksheets(); - $rls->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php b/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php deleted file mode 100644 index 800f349b7c..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/RichTextTest.php +++ /dev/null @@ -1,52 +0,0 @@ -getActiveSheet(); - $rtf = new RichText(); - $rtf->createText('~Cell Style~'); - $rtf->createTextRun('~RTF Style~')->getFont()?->setItalic(true); - $rtf->createText('~No Style~'); - $sheet->getCell('A1')->setValue($rtf); - $sheet->getStyle('A1')->getFont()->setBold(true); - - $fontStyle = $sheet->getStyle('A1')->getFont(); - self::assertTrue($fontStyle->getBold()); - self::assertFalse($fontStyle->getItalic()); - - $a1Value = $sheet->getCell('A1')->getValue(); - self::assertInstanceOf(RichText::class, $a1Value); - $elements = $a1Value->getRichTextElements(); - self::assertCount(3, $elements); - self::assertNull($elements[0]->getFont()); - $fontStyle = $elements[1]->getFont(); - self::assertNotNull($fontStyle); - self::assertFalse($fontStyle->getBold()); - self::assertTrue($fontStyle->getItalic()); - self::assertNull($elements[0]->getFont()); - - $writer = new HtmlWriter($spreadsheet); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString('td.style1, th.style1 { vertical-align:bottom; border-bottom:none #000000; border-top:none #000000; border-left:none #000000; border-right:none #000000; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:11pt }', $html, 'cell style'); - - self::assertStringContainsString('~Cell Style~', $html, 'cell style and first text element'); - - self::assertStringContainsString('~RTF Style~', $html, 'second text element'); - - self::assertStringContainsString('~No Style~', $html, 'third text element'); - - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/TextRotationTest.php b/tests/PhpSpreadsheetTests/Writer/Html/TextRotationTest.php deleted file mode 100644 index 2480e04b9e..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/TextRotationTest.php +++ /dev/null @@ -1,26 +0,0 @@ -getActiveSheet(); - $sheet->setPrintGridlines(true); - $sheet->getStyle('A7')->getAlignment()->setTextRotation(90); - $sheet->setCellValue('A7', 'Lorem Ipsum'); - $writer = new Html($spreadsheet); - $html = $writer->generateHtmlAll(); - self::assertStringContainsString(' transform:rotate(90deg);', $html); - $spreadsheet->disconnectWorksheets(); - unset($spreadsheet); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/TransparentDrawingsTest.php b/tests/PhpSpreadsheetTests/Writer/Html/TransparentDrawingsTest.php deleted file mode 100644 index faaf7e3544..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/TransparentDrawingsTest.php +++ /dev/null @@ -1,58 +0,0 @@ -getActiveSheet(); - $sheet->setShowGridLines(false); - - $drawing = new Drawing(); - $drawing->setName('Blue Square'); - $drawing->setPath('tests/data/Writer/XLSX/blue_square.png'); - self::assertEquals($drawing->getWidth(), 100); - self::assertEquals($drawing->getHeight(), 100); - $drawing->setCoordinates('A1'); - $drawing->setCoordinates2('E8'); - $drawing->setOpacity(25000); - $drawing->setWorksheet($sheet); - - $writer = new HtmlWriter($spreadsheet); - $content = $writer->generateHTMLAll(); - self::assertStringContainsString('opacity:0.25;', $content); - $spreadsheet->disconnectWorksheets(); - } - - public function testHtmlTransparentMemoryDrawing(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setShowGridLines(false); - - $contents = file_get_contents('tests/data/Writer/XLSX/blue_square.png'); - $drawing = MemoryDrawing::fromString("$contents"); - $drawing->setName('Blue Square'); - self::assertEquals($drawing->getWidth(), 100); - self::assertEquals($drawing->getHeight(), 100); - $drawing->setCoordinates('A1'); - $drawing->setCoordinates2('E8'); - $drawing->setOpacity(25000); - $drawing->setWorksheet($sheet); - - $writer = new HtmlWriter($spreadsheet); - $content = $writer->generateHTMLAll(); - self::assertStringContainsString('opacity:0.25;', $content); - $spreadsheet->disconnectWorksheets(); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/VisibilityTest.php b/tests/PhpSpreadsheetTests/Writer/Html/VisibilityTest.php deleted file mode 100644 index 04ec57720f..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/VisibilityTest.php +++ /dev/null @@ -1,113 +0,0 @@ -getActiveSheet(); - $sheet->setCellValue('A1', 1); - $sheet->setCellValue('A2', 2); - $sheet->setCellValue('A3', 3); - $sheet->setCellValue('B1', 4); - $sheet->setCellValue('B2', 5); - $sheet->setCellValue('B3', 6); - $sheet->setCellValue('C1', 7); - $sheet->setCellValue('C2', 8); - $sheet->setCellValue('C3', 9); - $sheet->getColumnDimension('B')->setVisible(false); - $sheet->getRowDimension(2)->setVisible(false); - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $reg = '/^\s*table[.]sheet0 tr { display:none; visibility:hidden }\s*$/m'; - $rowsrch = preg_match($reg, $html); - self::assertEquals($rowsrch, 0); - $reg = '/^\s*table[.]sheet0 tr[.]row1 { display:none; visibility:hidden }\s*$/m'; - $rowsrch = preg_match($reg, $html); - self::assertEquals($rowsrch, 1); - $reg = '/^\s*table[.]sheet0 [.]column1 [{] display:none [}]\s*$/m'; - $colsrch = preg_match($reg, $html); - self::assertEquals($colsrch, 1); - - $this->writeAndReload($spreadsheet, 'Html'); - } - - public function testVisibility2(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', 1); - $sheet->setCellValue('A2', 2); - $sheet->setCellValue('A3', 3); - $sheet->setCellValue('B1', 4); - $sheet->setCellValue('B2', 5); - $sheet->setCellValue('B3', 6); - $sheet->setCellValue('C1', 7); - $sheet->setCellValue('C2', 8); - $sheet->setCellValue('C3', 9); - $sheet->getDefaultRowDimension()->setVisible(false); - $sheet->getColumnDimension('B')->setVisible(false); - $sheet->getRowDimension(1)->setVisible(true); - $sheet->getRowDimension(3)->setVisible(true); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - $reg = '/^\s*table[.]sheet0 tr { height:15pt; display:none; visibility:hidden }\s*$/m'; - $rowsrch = preg_match($reg, $html); - self::assertEquals($rowsrch, 1); - $reg = '/^\s*table[.]sheet0 tr[.]row1 { display:none; visibility:hidden }\s*$/m'; - $rowsrch = preg_match($reg, $html); - self::assertEquals($rowsrch, 0); - $reg = '/^\s*table[.]sheet0 [.]column1 [{] display:none [}]\s*$/m'; - $colsrch = preg_match($reg, $html); - self::assertEquals($colsrch, 1); - - $this->writeAndReload($spreadsheet, 'Html'); - } - - public function testDefaultRowHeight(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', 1); - $sheet->getStyle('A1')->getFont()->setStrikethrough(true); - $sheet->setCellValue('A2', 2); - $sheet->setCellValue('A3', 3); - $sheet->getStyle('A3')->getFont()->setStrikethrough(true)->setUnderline(Font::UNDERLINE_SINGLE); - $sheet->setCellValue('B1', 4); - $sheet->setCellValue('B2', 5); - $sheet->setCellValue('B3', 6); - $sheet->setCellValue('C1', 7); - $sheet->setCellValue('C2', 8); - $sheet->setCellValue('C3', 9); - $sheet->getStyle('C3')->getFont()->setUnderline(Font::UNDERLINE_SINGLE); - $sheet->getDefaultRowDimension()->setRowHeight(20); - $sheet->getRowDimension(2)->setRowHeight(25); - - $writer = new Html($spreadsheet); - $html = $writer->generateHTMLAll(); - self::assertEquals(1, substr_count($html, 'height:20pt')); - self::assertEquals(1, substr_count($html, 'height:25pt')); - $rowsrch = preg_match('/^\s*table[.]sheet0 tr [{] height:20pt [}]\s*$/m', $html); - self::assertEquals(1, $rowsrch); - $rowsrch = preg_match('/^\s*table[.]sheet0 tr[.]row1 [{] height:25pt [}]\s*$/m', $html); - self::assertEquals(1, $rowsrch); - $rowsrch = preg_match('/^\s*td[.]style1, th[.]style1 [{].*text-decoration:line-through;.*[}]\s*$/m', $html); - self::assertEquals(1, $rowsrch); - $rowsrch = preg_match('/^\s*td[.]style2, th[.]style2 [{].*text-decoration:underline line-through;.*[}]\s*$/m', $html); - self::assertEquals(1, $rowsrch); - $rowsrch = preg_match('/^\s*td[.]style3, th[.]style3 [{].*text-decoration:underline;.*[}]\s*$/m', $html); - self::assertEquals(1, $rowsrch); - - $this->writeAndReload($spreadsheet, 'Html'); - } -} diff --git a/tests/PhpSpreadsheetTests/Writer/Html/XssVulnerabilityTest.php b/tests/PhpSpreadsheetTests/Writer/Html/XssVulnerabilityTest.php deleted file mode 100644 index 55d7a33662..0000000000 --- a/tests/PhpSpreadsheetTests/Writer/Html/XssVulnerabilityTest.php +++ /dev/null @@ -1,77 +0,0 @@ - ['Hello, I am safely viewing your site', 'Hello, I am safely viewing your site'], - 'link eliminated' => ["Google is here", "<a href='Visit Google'>Google is here</a>"], - 'script tag' => ["Hello, I am trying to your site", "Hello, I am trying to <script>alert('Hack');</script> your site"], - 'script tag with quotes' => ['Hello, I am trying to your site', 'Hello, I am trying to <script>alert("Hack");</script> your site'], - 'javascript tag no hex' => ["CLICK", "<a href='javascript:alert(1)'>CLICK</a>"], - 'javascript tag' => ["CLICK", "<a href='&#x2000;javascript:alert(1)'>CLICK</a>"], - 'with unicode' => ['CLICK', '<a href="\u0001java\u0003script:alert(1)">CLICK</a>'], - 'inline css' => ['
  • ', '<li style="list-style-image: url(javascript:alert(0))">'], - 'char value chevron' => ["\x3cscript src=http://www.example.com/malicious-code.js\x3e\x3c/script\x3e", '<script src=http://www.example.com/malicious-code.js></script>'], - 'hexadecimal html' => ['', '<IMG SRC=&#106&#x61&#x76&#x61&#x73&#109&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>'], - 'iframe' => ['', '<iframe width="560" onclick="alert(\'xss\')" height="315" src="https://www.youtube.com/embed/whatever?rel=0&controls=0&showinfo=0" frameborder="0" allowfullscreen></iframe>'], - ]; - } - - #[\PHPUnit\Framework\Attributes\DataProvider('providerXssRichText')] - public function testXssInComment(string $xssTextString, ?string $expected = null): void - { - $spreadsheet = new Spreadsheet(); - $startCell = ''; - $cellText = 'XSS Test'; - $endCell = $cellText . ''; - if ($expected === null) { // whole comment stripped away - $expected = $startCell . $endCell; - } else { - $expected = $startCell . '
    ' . $expected . '
    ' . PHP_EOL . $endCell; - } - - $richText = new RichText(); - $richText->createText($xssTextString); - - $spreadsheet->getActiveSheet()->getCell('A1')->setValue($cellText); - - $spreadsheet->getActiveSheet() - ->getComment('A1') - ->setText($richText); - - $writer = new Html($spreadsheet); - - $verify = $writer->generateHtmlAll(); - // Ensure that executable js has been stripped from the comments - self::assertStringContainsString($expected, $verify); - $spreadsheet->disconnectWorksheets(); - } - - public function testXssInFontName(): void - { - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->getCell('A1')->setValue('here'); - $used = 'Calibri - - - - - a - a-1 - 1 - - - b - b-2 - 2 - - - c - c-3 - 3 - -
    - - -
    -